private function buildAssociationValue(ClassMetadata $metadata, $propertyPath, $value)
    {
        $childMetadata = $this->manager->getClassMetadata(
            $metadata->getAssociationTargetClass($propertyPath)
        );

        // Single association
        if ($metadata->isSingleValuedAssociation($propertyPath)) {
            if (is_string($value) && '#' === substr($value, 0, 1)) {
                return $this->getReference(substr($value, 1));
            } elseif (is_array($value)) {
                return $this->buildEntity($childMetadata, $value);
            }
            throw new \Exception("Unexpected value for single association '$propertyPath'.");

        // Collection association
        } elseif ($metadata->isCollectionValuedAssociation($propertyPath)) {
            if (!is_array($value)) {
                throw new \Exception('Expected array.');
            }
            $builtValue = [];
            foreach ($value as $childData) {
                if (is_string($childData) && '#' === substr($childData, 0, 1)) {
                    array_push($builtValue, $this->getReference(substr($childData, 1)));
                } elseif (is_array($value)) {
                    array_push($builtValue, $this->buildEntity($childMetadata, $childData));
                } else {
                    throw new \Exception("Unexpected value for association '$propertyPath'.");
                }
            }
            return $builtValue;
        }
        throw new \Exception("Unexpected association path '$propertyPath'.");
    }