/**
  * @param string    $field
  * @param \StdClass $source
  * @param object    $entity
  *
  * @return array|Proxy|object
  * @throws HydrationException
  * @throws MappingException
  */
 private function hydrateAssociation($field, $entity, $source)
 {
     $accessor = new PropertyAccessor();
     $targetClassName = $this->metadata->getAssociationTargetClass($field);
     $mapping = $this->metadata->getAssociationMapping($field);
     $targetPersister = $this->manager->getUnitOfWork()->getEntityPersister($targetClassName);
     $targetMetadata = $this->manager->getClassMetadata($mapping['target']);
     $apiField = $mapping['api_field'];
     $field = $mapping['field'];
     if ($this->metadata->isSingleValuedAssociation($field)) {
         $identifiers = $this->metadata->getIdentifierValues($entity);
         if ($mapping['isOwningSide']) {
             try {
                 $value = $accessor->getValue($source, $apiField);
             } catch (NoSuchPropertyException $exception) {
                 if ($mapping['nullable']) {
                     return null;
                 }
                 throw new HydrationException(sprintf('Api field %s for property %s does not present in response', $apiField, $field));
             }
             if ($targetMetadata->isIdentifierComposite()) {
                 throw new HydrationException('Composite references not supported');
             }
             $targetIdsNames = $targetMetadata->getIdentifierFieldNames();
             $targetIdName = array_shift($targetIdsNames);
             $type = $this->manager->getConfiguration()->getTypeRegistry()->get($targetMetadata->getTypeOfField($targetIdName));
             $identifiers = [$targetIdName => $type->fromApiValue($value)];
         }
         return $targetPersister->getToOneEntity($mapping, $entity, $identifiers);
     }
     if ($this->metadata->isCollectionValuedAssociation($field)) {
         return $targetPersister->getOneToManyCollection($mapping, $entity);
     }
     throw new MappingException('Invalid metadata association type');
 }
 /**
  * Loads a list of entities by a list of field criteria.
  *
  * @param array      $criteria
  * @param array|null $orderBy
  * @param int|null   $limit
  * @param int|null   $offset
  *
  * @return Collection
  */
 public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null)
 {
     $client = $this->manager->getConfiguration()->getRegistry()->get($this->metadata->getClientName());
     /** @var Searcher $searcher */
     $searcherClass = $this->metadata->getSearcherClass();
     $searcher = new $searcherClass($this->manager);
     $apiCriteria = [];
     foreach ($criteria as $field => $values) {
         if ($this->metadata->hasAssociation($field)) {
             $mapping = $this->metadata->getAssociationMapping($field);
             /** @var EntityMetadata $target */
             $target = $this->manager->getClassMetadata($mapping['target']);
             $converter = function ($value) use($target) {
                 if (!is_object($value)) {
                     return $value;
                 }
                 $ids = $target->getIdentifierValues($value);
                 if ($target->isIdentifierComposite) {
                     return $ids;
                 }
                 return array_shift($ids);
             };
             if (is_array($values)) {
                 $values = array_map($converter, $values);
             } else {
                 $values = $converter($values);
             }
         }
         $apiCriteria[$this->metadata->getApiFieldName($field)] = $values;
     }
     $apiOrder = [];
     foreach ((array) $orderBy as $field => $direction) {
         $apiOrder[$this->metadata->getApiFieldName($field)] = $direction;
     }
     $objects = $searcher->search($client, $this->metadata, [$apiCriteria, $apiOrder, $limit, $offset]);
     $entities = [];
     foreach ($objects as $object) {
         $entities[] = $this->manager->getUnitOfWork()->getOrCreateEntity($this->metadata->getName(), $object);
     }
     return new ArrayCollection($entities);
 }
 /**
  * @return RpcClientInterface
  */
 protected function getClient()
 {
     return $this->manager->getConfiguration()->getRegistry()->get($this->metadata->getClientName());
 }
 /** {@inheritdoc} */
 protected function initialize()
 {
     $this->driver = $this->manager->getConfiguration()->getDriver();
     $this->initialized = true;
 }