/**
  * Will return one pointcut which does specifically only match the joinpoints of the structure
  * which this docblock belongs to
  *
  * @param string $docBlock   The DocBlock to search in
  * @param string $targetType Type of the target any resulting joinpoints have, e.g. Joinpoint::TARGET_METHOD
  * @param string $targetName Name of the target any resulting joinpoints have
  *
  * @return \AppserverIo\Doppelgaenger\Entities\Lists\PointcutExpressionList
  */
 public function getPointcutExpressions($docBlock, $targetType, $targetName)
 {
     $pointcutExpressions = new PointcutExpressionList();
     // get our tokenizer and parse the doc Block
     $tokenizer = new Tokenizer();
     $tokenizer->ignore(array('param', 'return', 'throws'));
     $tokens = new Tokens($tokenizer->parse($docBlock));
     // 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) {
         // filter out the annotations which are no proper join-points
         if (!class_exists('\\AppserverIo\\Psr\\MetaobjectProtocol\\Aop\\Annotations\\Advices\\' . $annotation->name)) {
             continue;
         }
         // build the join-point
         $joinpoint = new Joinpoint();
         $joinpoint->setTarget($targetType);
         $joinpoint->setCodeHook($annotation->name);
         $joinpoint->setStructure($this->currentDefinition->getQualifiedName());
         $joinpoint->setTargetName($targetName);
         // build the pointcut(s)
         foreach ($annotation->values as $rawAdvice) {
             // as it might be an array we have to sanitize it first
             if (!is_array($rawAdvice)) {
                 $rawAdvice = array($rawAdvice);
             }
             foreach ($rawAdvice as $adviceString) {
                 // create the pointcut
                 $pointcutExpression = new PointcutExpression($adviceString);
                 $pointcutExpression->setJoinpoint($joinpoint);
                 $pointcutExpressions->add($pointcutExpression);
             }
         }
     }
     return $pointcutExpressions;
 }
 /**
  * Will look at all advices known to the aspect register and filter out pointcut expressions matching the
  * function in question
  * Will return a list of pointcut expressions including distinctive pointcuts to weave in the associated advices
  *
  * @param FunctionDefinition $functionDefinition Definition of the function to match known advices against
  *
  * @return \AppserverIo\Doppelgaenger\Entities\Lists\PointcutExpressionList
  */
 protected function findAdvicePointcutExpressions(FunctionDefinition $functionDefinition)
 {
     // we have to search for all advices, all of their pointcuts and all pointcut expressions those reference
     $pointcutExpressions = new PointcutExpressionList();
     foreach ($this->aspectRegister as $aspect) {
         foreach ($aspect->getAdvices() as $advice) {
             foreach ($advice->getPointcuts() as $pointcut) {
                 // there should be no other pointcuts than those referencing pointcut definitions
                 if (!$pointcut instanceof PointcutPointcut) {
                     continue;
                 }
                 foreach ($pointcut->getReferencedPointcuts() as $referencedPointcut) {
                     if ($referencedPointcut->getPointcutExpression()->getPointcut()->matches($functionDefinition)) {
                         // we found a pointcut of an advice that matches!
                         // lets create a distinctive join-point and add the advice weaving to the pointcut.
                         // Make a clone so that there are no weird reference shenanigans
                         $pointcutExpression = clone $referencedPointcut->getPointcutExpression();
                         $joinpoint = new Joinpoint();
                         $joinpoint->setCodeHook($advice->getCodeHook());
                         $joinpoint->setStructure($functionDefinition->getStructureName());
                         $joinpoint->setTarget(Joinpoint::TARGET_METHOD);
                         $joinpoint->setTargetName($functionDefinition->getName());
                         $pointcutExpression->setJoinpoint($joinpoint);
                         // "straighten out" structure and function referenced by the pointcut to avoid regex within generated code.
                         // Same here with the cloning: we do not want to influence the matching process with working on references
                         $expressionPointcut = clone $pointcutExpression->getPointcut();
                         $expressionPointcut->straightenExpression($functionDefinition);
                         // add the weaving pointcut into the expression
                         $pointcutExpression->setPointcut(new AndPointcut(AdvisePointcut::TYPE . str_replace('\\\\', '\\', '(\\' . $advice->getQualifiedName() . ')'), $expressionPointcut->getType() . '(' . $expressionPointcut->getExpression() . ')'));
                         $pointcutExpression->setString($expressionPointcut->getExpression());
                         // add it to our result list
                         $pointcutExpressions->add($pointcutExpression);
                         // break here as we only need one, they are implicitly "or" combined
                         break;
                     }
                 }
             }
         }
     }
     return $pointcutExpressions;
 }