/**
  * Will generate the code used before the original function body
  *
  * @param bool               $injectNeeded       Determine if we have to use a try...catch block
  * @param FunctionDefinition $functionDefinition The function definition object
  *
  * @return string
  */
 protected function generateBeforeCode($injectNeeded, FunctionDefinition $functionDefinition)
 {
     $suffix = PBC_ORIGINAL_FUNCTION_SUFFIX . str_replace('.', '', microtime(true));
     $code = PBC_CONTRACT_CONTEXT . ' = \\TechDivision\\PBC\\ContractContext::open();';
     // Invariant is not needed in private or static functions.
     // Also make sure that there is none in front of the constructor check
     if ($functionDefinition->getVisibility() !== 'private' && !$functionDefinition->getIsStatic() && $functionDefinition->getName() !== '__construct') {
         $code .= PBC_INVARIANT_PLACEHOLDER . PBC_PLACEHOLDER_CLOSE;
     }
     $code .= PBC_PRECONDITION_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE . PBC_OLD_SETUP_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE;
     // If we inject something we might need a try ... catch around the original call.
     if ($injectNeeded === true) {
         $code .= 'try {';
     }
     // Build up the call to the original function.
     $code .= PBC_KEYWORD_RESULT . ' = ' . $functionDefinition->getHeader('call', $suffix) . ';';
     // Finish the try ... catch and place the inject marker
     if ($injectNeeded === true) {
         $code .= '} catch (\\Exception $e) {}' . PBC_METHOD_INJECT_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE;
     }
     // No just place all the other placeholder for other filters to come
     $code .= PBC_POSTCONDITION_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE;
     // Invariant is not needed in private or static functions
     if ($functionDefinition->getVisibility() !== 'private' && !$functionDefinition->getIsStatic()) {
         $code .= PBC_INVARIANT_PLACEHOLDER . PBC_PLACEHOLDER_CLOSE;
     }
     $code .= 'if (' . PBC_CONTRACT_CONTEXT . ') {\\TechDivision\\PBC\\ContractContext::close();}
         return ' . PBC_KEYWORD_RESULT . ';}';
     $code .= $functionDefinition->getHeader('definition', $suffix, true) . '{';
     return $code;
 }
 /**
  * This method will add all assertions any ancestral structures (parent classes, implemented interfaces) might have
  * to the passed class definition.
  *
  * @param \TechDivision\PBC\Entities\Definitions\FunctionDefinition $functionDefinition The function definition
  *                                                                                      we are working on
  *
  * @return void
  */
 protected function addAncestralAssertions(FunctionDefinition $functionDefinition)
 {
     $dependencies = $this->currentDefinition->getDependencies();
     foreach ($dependencies as $dependency) {
         // freshly set the dependency definition to avoid side effects
         $dependencyDefinition = null;
         $fileEntry = $this->structureMap->getEntry($dependency);
         if (!$fileEntry instanceof Structure) {
             // Continue, don't fail as we might have dependencies which are not under PBC surveillance
             continue;
         }
         // Get the needed parser
         $structureParserFactory = new StructureParserFactory();
         $parser = $structureParserFactory->getInstance($fileEntry->getType(), $fileEntry->getPath(), $this->config, $this->structureMap, $this->structureDefinitionHierarchy);
         // Get the definition
         $dependencyDefinition = $parser->getDefinition($dependency, true);
         // Get the function definitions of the dependency structure
         $dependencyFunctionDefinitions = $dependencyDefinition->getFunctionDefinitions();
         // If we have a method with the name of the current one we have to get the conditions as ancestrals
         if ($dependencyFunctionDefinitions->entryExists($functionDefinition->getName())) {
             // Get the definition
             $dependencyFunctionDefinition = $dependencyFunctionDefinitions->get($functionDefinition->getName());
             // If the ancestral function uses the old keyword we have to do too
             if ($dependencyFunctionDefinition->getUsesOld() !== false) {
                 $functionDefinition->usesOld = true;
             }
             // Get the conditions
             $functionDefinition->ancestralPreconditions = $dependencyFunctionDefinition->getAllPreconditions(true);
             $functionDefinition->ancestralPostconditions = $dependencyFunctionDefinition->getAllPostconditions(true);
         }
     }
 }
 /**
  * Will change code to create an entry for the old object state.
  *
  * @param string                                                    $bucketData         Payload of the currently
  *                                                                                       filtered bucket
  * @param \TechDivision\PBC\Entities\Definitions\FunctionDefinition $functionDefinition Currently handled function
  *
  * @throws \TechDivision\PBC\Exceptions\GeneratorException
  *
  * @return boolean
  */
 private function injectOldCode(&$bucketData, FunctionDefinition &$functionDefinition)
 {
     // Do we even need to do anything?
     if ($functionDefinition->getUsesOld() !== true) {
         return false;
     }
     // If the function is static it should not use the pbcOld keyword as there is no state to the class!
     if ($functionDefinition->getIsStatic() === true) {
         throw new GeneratorException('Cannot clone class state in static method ' . $functionDefinition->getName());
     }
     // Still here? Then inject the clone statement to preserve an instance of the object prior to our call.
     $bucketData = str_replace(PBC_OLD_SETUP_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE, PBC_KEYWORD_OLD . ' = clone $this;', $bucketData);
     // Still here? We encountered no error then.
     return true;
 }