/**
  * {@inheritDoc}
  */
 public function createMetadata($reference)
 {
     // clear the method arrays
     $this->getters = [];
     $this->setters = [];
     $this->adders = [];
     $ref = new \ReflectionClass($reference);
     $this->findClayMethods($ref);
     $entityMetadata = new EntityMetadata($ref->getName());
     /*
     For each setter (or adder) that has a getter (e.g. a property that is fully accessible) check if it has a
     relationship to another entity class, otherwise detect the property type
     */
     foreach ($this->setters as $property => $setterMethod) {
         if (empty($this->getters[$property])) {
             // can't continue without a getter
             continue;
         }
         /** @var \ReflectionMethod $setterMethod */
         /** @var \ReflectionParameter $valueParam */
         $valueParam = $setterMethod->getParameters()[0];
         if ($valueParam->isArray()) {
             // this is a collection, check for an adder so we can check type on the collection elements
             if (!empty($this->adders[$property])) {
                 $setterMethod = $this->adders[$property];
                 $arguments = $setterMethod->getParameters();
                 // take the last argument, as the value parameter will be #2 for adders that apply to associative arrays
                 $valueParam = end($arguments);
             }
         }
         $class = $valueParam->getClass();
         // ignore properties that have relationships with other entities
         if (empty($class) || empty($class->getNamespaceName())) {
             /** @var \ReflectionMethod $getterMethod */
             $getterMethod = $this->getters[$property];
             $getter = $getterMethod->getName();
             $setter = $setterMethod->getName();
             if ($valueParam->isArray()) {
                 $type = EntityMetadata::FIELD_TYPE_ARRAY;
             } else {
                 // detect type
                 $type = $this->detectPropertyType($this->owningClass[$property], $getter, $setter, $property);
             }
             $fieldMetadata = [EntityMetadata::METADATA_FIELD_TYPE => $type, EntityMetadata::METADATA_FIELD_GETTER => $getter, EntityMetadata::METADATA_FIELD_SETTER => $setter];
             // underscore the property name
             $property = $this->toSplitCase($property);
             $entityMetadata->addFieldMetadata($property, $fieldMetadata);
         }
     }
     return $entityMetadata;
 }
 /**
  * @dataProvider pkMetadataProvider
  *
  * @param $fieldMetadata
  * @param $expectedMetadata
  */
 public function testPublicKeyMetadata($fieldMetadata, $expectedMetadata)
 {
     $pk = "id";
     $metadata = new EntityMetadata("blah");
     $metadata->setPrimaryKey($pk);
     if (!is_null($fieldMetadata)) {
         $metadata->addFieldMetadata($pk, $fieldMetadata);
     }
     $pkMetadata = $metadata->getPrimaryKeyMetadata();
     foreach ($expectedMetadata as $field => $value) {
         $this->assertEquals($value, $pkMetadata[$field]);
     }
 }