/**
  * @param  AbstractRelationMapping $fieldMapping
  * @param  string                  $relatedName
  * @param  string                  $methodPrefix
  * @param  string                  $relatedMethodPrefix
  * @param  string                  $collectionMethodName
  * @param  Arg                     $relatedArgument
  * @return Node
  */
 protected function getBidiretionalMethodNode(AbstractRelationMapping $fieldMapping, $relatedName, $methodPrefix, $relatedMethodPrefix, $collectionMethodName, $relatedArgument)
 {
     $name = $fieldMapping->getName();
     $singularName = StringUtil::singularify($name);
     $singularRelatedName = StringUtil::singularify($relatedName);
     $targetModel = $fieldMapping->getTargetModel();
     return new ClassMethod($methodPrefix . ucfirst($singularName), array('type' => 1, 'params' => array(new Param($singularName, null, new Name($targetModel)), new Param('stopPropagation', new ConstFetch(new Name('false')))), 'stmts' => array(new MethodCall(new PropertyFetch(new Variable('this'), $name), $collectionMethodName, array(new Arg(new Variable($singularName)))), new If_(new BooleanNot(new Variable('stopPropagation')), array('stmts' => array(new MethodCall(new Variable($singularName), $relatedMethodPrefix . ucfirst($singularRelatedName), array($relatedArgument, new Arg(new ConstFetch(new Name('true')))))))), new Return_(new Variable('this')))), array('comments' => array(new Comment(new Documentor(array(new ParamRow($targetModel, $singularName), new ParamRow('bool', 'stopPropagation'), new ReturnRow('$this')))))));
 }
 /**
  * @param  FieldMappingInterface $fieldMapping
  * @return Node
  */
 protected function getUnidirectionalRemoveMethodNode(FieldMappingInterface $fieldMapping)
 {
     if (!$fieldMapping instanceof Many2ManyOwningSideMapping) {
         throw new \InvalidArgumentException('Field mapping has to be Many2ManyOwningSideMapping!');
     }
     $name = $fieldMapping->getName();
     $singularName = StringUtil::singularify($name);
     $targetModel = $fieldMapping->getTargetModel();
     return new ClassMethod('remove' . ucfirst($singularName), array('type' => 1, 'params' => array(new Param($singularName, null, new Name($targetModel))), 'stmts' => array(new MethodCall(new PropertyFetch(new Variable('this'), $name), 'removeElement', array(new Arg(new Variable($singularName)))), new Return_(new Variable('this')))), array('comments' => array(new Comment(new Documentor(array(new ParamRow($targetModel, $singularName), new ReturnRow('$this')))))));
 }
 /**
  * @param  FieldMappingInterface $fieldMapping
  * @return Node
  */
 protected function getBidiretionalSetterMethodNode(FieldMappingInterface $fieldMapping)
 {
     if (!$fieldMapping instanceof AbstractMany2ManyMapping) {
         throw new \InvalidArgumentException('Field mapping has to be AbstractMany2ManyMapping!');
     }
     $name = $fieldMapping->getName();
     $singularName = StringUtil::singularify($name);
     $targetModel = $fieldMapping->getTargetModel();
     return new ClassMethod('set' . ucfirst($name), array('type' => 1, 'params' => array(new Param($name)), 'stmts' => array(new Foreach_(new PropertyFetch(new Variable('this'), $name), new Variable($singularName), array('stmts' => array(new MethodCall(new Variable('this'), 'remove' . ucfirst($singularName), array(new Arg(new Variable($singularName))))))), new Foreach_(new Variable($name), new Variable($singularName), array('stmts' => array(new MethodCall(new Variable('this'), 'add' . ucfirst($singularName), array(new Arg(new Variable($singularName))))))), new Return_(new Variable('this')))), array('comments' => array(new Comment(new Documentor(array(new ParamRow($targetModel . '[]|\\Doctrine\\Common\\Collections\\Collection', $name), new ReturnRow('$this')))))));
 }
 /**
  * @param  FieldMappingInterface $fieldMapping
  * @return Node[]
  */
 public function getMethodsNodes(FieldMappingInterface $fieldMapping)
 {
     if (!$fieldMapping instanceof Many2OneMapping) {
         throw new \InvalidArgumentException('Field mapping has to be Many2OneMapping!');
     }
     if (null === ($inversedBy = $fieldMapping->getInversedBy())) {
         return array($this->getUnidirectionalSetterMethodNode($fieldMapping), $this->getGetterMethodNode($fieldMapping->getName(), $fieldMapping->getTargetModel()));
     }
     return array($this->getBidiretionalSetterMethodNode($fieldMapping, StringUtil::singularify($inversedBy), 'remove', 'add'), $this->getGetterMethodNode($fieldMapping->getName(), $fieldMapping->getTargetModel()));
 }
 public function testSingularifyWithMultiplePossibleResult()
 {
     $this->assertEquals('analys', StringUtil::singularify('analyses'));
     $this->assertEquals('hippopotamus', StringUtil::singularify('hippopotamuses'));
 }