diff --git a/composer.json b/composer.json
index 761aae6d50d361bb0c5b345d3c274e4476bc65e6..88ac5690595258bf832bd73ca64e55909443f2ba 100644
--- a/composer.json
+++ b/composer.json
@@ -39,9 +39,12 @@
     "symfony/config": "^4.2",
     "symfony/contracts": "^1.0",
     "symfony/dependency-injection": "^4.2",
+    "symfony/http-foundation": "^4.2",
     "symfony/http-kernel": "^4.2",
     "symfony/property-info": "^4.2",
-    "symfony/proxy-manager-bridge": "^4.2"
+    "symfony/proxy-manager-bridge": "^4.2",
+    "symfony/routing": "^4.2",
+    "symfony/serializer": "^4.2"
   },
   "require-dev": {
     "ext-pdo_sqlite": "*",
@@ -68,7 +71,6 @@
     "symfony/browser-kit": "^4.2",
     "symfony/debug": "^4.2",
     "symfony/framework-bundle": "^4.2",
-    "symfony/serializer": "^4.2",
     "symfony/translation": "^4.2",
     "symfony/validator": "^4.2",
     "symfony/var-dumper": "^4.2",
diff --git a/composer.lock b/composer.lock
index 639d6b717ca695c4778ef80fb9c6ad4afb999fe1..ebe9ddfd397f709e725ab2d523ab9ed6719f9e72 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "6c238282f1b48d979bde4c598b67a27b",
+    "content-hash": "5aa2b50ddb088fca3c60c64c4dcbf891",
     "packages": [
         {
             "name": "api-platform/core",
@@ -1186,20 +1186,21 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v4.2.8",
+            "version": "v4.3.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-foundation.git",
-                "reference": "1ea878bd3af18f934dedb8c0de60656a9a31a718"
+                "reference": "b7e4945dd9b277cd24e93566e4da0a87956392a9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1ea878bd3af18f934dedb8c0de60656a9a31a718",
-                "reference": "1ea878bd3af18f934dedb8c0de60656a9a31a718",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b7e4945dd9b277cd24e93566e4da0a87956392a9",
+                "reference": "b7e4945dd9b277cd24e93566e4da0a87956392a9",
                 "shasum": ""
             },
             "require": {
                 "php": "^7.1.3",
+                "symfony/mime": "^4.3",
                 "symfony/polyfill-mbstring": "~1.1"
             },
             "require-dev": {
@@ -1209,7 +1210,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "4.2-dev"
+                    "dev-master": "4.3-dev"
                 }
             },
             "autoload": {
@@ -1236,7 +1237,7 @@
             ],
             "description": "Symfony HttpFoundation Component",
             "homepage": "https://symfony.com",
-            "time": "2019-05-01T08:36:31+00:00"
+            "time": "2019-06-06T10:05:02+00:00"
         },
         {
             "name": "symfony/http-kernel",
@@ -1385,6 +1386,65 @@
             ],
             "time": "2019-01-16T20:31:39+00:00"
         },
+        {
+            "name": "symfony/mime",
+            "version": "v4.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/mime.git",
+                "reference": "ec2c5565de60e03f33d4296a655e3273f0ad1f8b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/mime/zipball/ec2c5565de60e03f33d4296a655e3273f0ad1f8b",
+                "reference": "ec2c5565de60e03f33d4296a655e3273f0ad1f8b",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1.3",
+                "symfony/polyfill-intl-idn": "^1.10",
+                "symfony/polyfill-mbstring": "^1.0"
+            },
+            "require-dev": {
+                "egulias/email-validator": "^2.0",
+                "symfony/dependency-injection": "~3.4|^4.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.3-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Mime\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "A library to manipulate MIME messages",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "mime",
+                "mime-type"
+            ],
+            "time": "2019-06-04T09:22:54+00:00"
+        },
         {
             "name": "symfony/polyfill-ctype",
             "version": "v1.11.0",
@@ -1443,6 +1503,68 @@
             ],
             "time": "2019-02-06T07:57:58+00:00"
         },
+        {
+            "name": "symfony/polyfill-intl-idn",
+            "version": "v1.11.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-intl-idn.git",
+                "reference": "c766e95bec706cdd89903b1eda8afab7d7a6b7af"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c766e95bec706cdd89903b1eda8afab7d7a6b7af",
+                "reference": "c766e95bec706cdd89903b1eda8afab7d7a6b7af",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "symfony/polyfill-mbstring": "^1.3",
+                "symfony/polyfill-php72": "^1.9"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Idn\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                },
+                {
+                    "name": "Laurent Bassin",
+                    "email": "laurent@bassin.info"
+                }
+            ],
+            "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "idn",
+                "intl",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "time": "2019-03-04T13:44:35+00:00"
+        },
         {
             "name": "symfony/polyfill-mbstring",
             "version": "v1.11.0",
@@ -1502,6 +1624,61 @@
             ],
             "time": "2019-02-06T07:57:58+00:00"
         },
+        {
+            "name": "symfony/polyfill-php72",
+            "version": "v1.11.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php72.git",
+                "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c",
+                "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.11-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php72\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "time": "2019-02-06T07:57:58+00:00"
+        },
         {
             "name": "symfony/property-access",
             "version": "v4.2.8",
@@ -1702,18 +1879,94 @@
             "homepage": "https://symfony.com",
             "time": "2019-04-16T11:19:53+00:00"
         },
+        {
+            "name": "symfony/routing",
+            "version": "v4.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/routing.git",
+                "reference": "9b31cd24f6ad2cebde6845f6daa9c6d69efe2465"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/routing/zipball/9b31cd24f6ad2cebde6845f6daa9c6d69efe2465",
+                "reference": "9b31cd24f6ad2cebde6845f6daa9c6d69efe2465",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1.3"
+            },
+            "conflict": {
+                "symfony/config": "<4.2",
+                "symfony/dependency-injection": "<3.4",
+                "symfony/yaml": "<3.4"
+            },
+            "require-dev": {
+                "doctrine/annotations": "~1.2",
+                "psr/log": "~1.0",
+                "symfony/config": "~4.2",
+                "symfony/dependency-injection": "~3.4|~4.0",
+                "symfony/expression-language": "~3.4|~4.0",
+                "symfony/http-foundation": "~3.4|~4.0",
+                "symfony/yaml": "~3.4|~4.0"
+            },
+            "suggest": {
+                "doctrine/annotations": "For using the annotation loader",
+                "symfony/config": "For using the all-in-one router or any loader",
+                "symfony/expression-language": "For using expression matching",
+                "symfony/http-foundation": "For using a Symfony Request object",
+                "symfony/yaml": "For using the YAML loader"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.3-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Routing\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Routing Component",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "router",
+                "routing",
+                "uri",
+                "url"
+            ],
+            "time": "2019-06-05T09:16:20+00:00"
+        },
         {
             "name": "symfony/serializer",
-            "version": "v4.2.8",
+            "version": "v4.3.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/serializer.git",
-                "reference": "543bf3d7d4be76e878dc78c82328e978d57dd44d"
+                "reference": "7a05742647711bc371e9fa1d71206561b88d093a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/serializer/zipball/543bf3d7d4be76e878dc78c82328e978d57dd44d",
-                "reference": "543bf3d7d4be76e878dc78c82328e978d57dd44d",
+                "url": "https://api.github.com/repos/symfony/serializer/zipball/7a05742647711bc371e9fa1d71206561b88d093a",
+                "reference": "7a05742647711bc371e9fa1d71206561b88d093a",
                 "shasum": ""
             },
             "require": {
@@ -1753,7 +2006,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "4.2-dev"
+                    "dev-master": "4.3-dev"
                 }
             },
             "autoload": {
@@ -1780,7 +2033,7 @@
             ],
             "description": "Symfony Serializer Component",
             "homepage": "https://symfony.com",
-            "time": "2019-04-28T07:09:27+00:00"
+            "time": "2019-06-05T13:25:51+00:00"
         },
         {
             "name": "symfony/var-exporter",
@@ -7556,61 +7809,6 @@
             ],
             "time": "2019-02-06T07:57:58+00:00"
         },
-        {
-            "name": "symfony/polyfill-php72",
-            "version": "v1.11.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/polyfill-php72.git",
-                "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c",
-                "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.11-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Polyfill\\Php72\\": ""
-                },
-                "files": [
-                    "bootstrap.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Nicolas Grekas",
-                    "email": "p@tchwork.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
-            "homepage": "https://symfony.com",
-            "keywords": [
-                "compatibility",
-                "polyfill",
-                "portable",
-                "shim"
-            ],
-            "time": "2019-02-06T07:57:58+00:00"
-        },
         {
             "name": "symfony/process",
             "version": "v4.2.8",
@@ -7660,82 +7858,6 @@
             "homepage": "https://symfony.com",
             "time": "2019-04-10T16:20:36+00:00"
         },
-        {
-            "name": "symfony/routing",
-            "version": "v4.2.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/routing.git",
-                "reference": "f4e43bb0dff56f0f62fa056c82d7eadcdb391bab"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/routing/zipball/f4e43bb0dff56f0f62fa056c82d7eadcdb391bab",
-                "reference": "f4e43bb0dff56f0f62fa056c82d7eadcdb391bab",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^7.1.3"
-            },
-            "conflict": {
-                "symfony/config": "<4.2",
-                "symfony/dependency-injection": "<3.4",
-                "symfony/yaml": "<3.4"
-            },
-            "require-dev": {
-                "doctrine/annotations": "~1.0",
-                "psr/log": "~1.0",
-                "symfony/config": "~4.2",
-                "symfony/dependency-injection": "~3.4|~4.0",
-                "symfony/expression-language": "~3.4|~4.0",
-                "symfony/http-foundation": "~3.4|~4.0",
-                "symfony/yaml": "~3.4|~4.0"
-            },
-            "suggest": {
-                "doctrine/annotations": "For using the annotation loader",
-                "symfony/config": "For using the all-in-one router or any loader",
-                "symfony/expression-language": "For using expression matching",
-                "symfony/http-foundation": "For using a Symfony Request object",
-                "symfony/yaml": "For using the YAML loader"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "4.2-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Routing\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Routing Component",
-            "homepage": "https://symfony.com",
-            "keywords": [
-                "router",
-                "routing",
-                "uri",
-                "url"
-            ],
-            "time": "2019-04-27T09:38:08+00:00"
-        },
         {
             "name": "symfony/stopwatch",
             "version": "v4.2.8",
diff --git a/src/Factory/Property/ResourcePropertyFactory.php b/src/Factory/Property/ResourcePropertyFactory.php
index a179e17da5c441ef95f5f4c89d42ce09eecb9d7c..ca08211abbe80c6de6ea708140393ec6e71f8ccb 100644
--- a/src/Factory/Property/ResourcePropertyFactory.php
+++ b/src/Factory/Property/ResourcePropertyFactory.php
@@ -73,11 +73,32 @@ class ResourcePropertyFactory implements PropertyFactoryInterface
             return $this->next->create($class, $name, $context);
         }
 
+        [$type, $typeMeta] = $this->getPropertyType($property, $context);
+
+        return new PropertyMetadata(
+            $name,
+            $typeMeta,
+            $type->isNullable() ?: false,
+            $property->isReadable() ?: false,
+            $property->isWritable() ?: false,
+            $property->isInitializable() ?: false,
+            $property->isIdentifier() ?: false
+        );
+    }
+
+    /**
+     * @param \ApiPlatform\Core\Metadata\Property\PropertyMetadata $property
+     * @param ContextInterface                                     $context
+     *
+     * @return array
+     */
+    private function getPropertyType(\ApiPlatform\Core\Metadata\Property\PropertyMetadata $property, ContextInterface $context): array
+    {
         $type = PropertyInfoType::notNull($property->getType());
         $typeMeta = $context->createType($type, $context);
 
         if (!$property->isReadableLink() && !$property->isWritableLink()) {
-            $typeMeta = $typeMeta->fmap(function (TypeMetadata $t) {
+            $typeMeta = $typeMeta->fmap(static function (TypeMetadata $t) {
                 if ($t instanceof ResourceMetadata) {
                     return new ResourceLinkMetadata($t);
                 }
@@ -86,15 +107,7 @@ class ResourcePropertyFactory implements PropertyFactoryInterface
             });
         }
 
-        return new PropertyMetadata(
-            $name,
-            $typeMeta,
-            $type->isNullable() ?: false,
-            $property->isReadable() ?: false,
-            $property->isWritable() ?: false,
-            $property->isInitializable() ?: false,
-            $property->isIdentifier() ?: false
-        );
+        return [$type, $typeMeta];
     }
 
     /**
diff --git a/src/Helper/TypeFunctorHelper.php b/src/Helper/TypeFunctorHelper.php
index 4f75e33e647083f191d64ce2a2f79f57fd212ed4..6b2700852f9e5a0f7fb5e9591b70fd22eb890c55 100644
--- a/src/Helper/TypeFunctorHelper.php
+++ b/src/Helper/TypeFunctorHelper.php
@@ -29,15 +29,15 @@ class TypeFunctorHelper
 {
     /**
      * @param TypeFunctor[] $items
-     * @param callable      $f
+     * @param callable      $func
      *
      * @return TypeFunctor[]
      */
-    public static function map(array $items, callable $f): array
+    public static function map(array $items, callable $func): array
     {
         return array_map(
-            function (TypeFunctor $item) use ($f) {
-                return self::null($item, $f);
+            function (TypeFunctor $item) use ($func) {
+                return self::null($item, $func);
             },
             $items
         );
@@ -45,12 +45,12 @@ class TypeFunctorHelper
 
     /**
      * @param TypeFunctor|null $item
-     * @param callable         $f
+     * @param callable         $func
      *
      * @return TypeFunctor|null
      */
-    public static function null(?TypeFunctor $item, callable $f): ?TypeFunctor
+    public static function null(?TypeFunctor $item, callable $func): ?TypeFunctor
     {
-        return $item ? $item->fmap($f) : null;
+        return $item ? $item->fmap($func) : null;
     }
 }
diff --git a/src/JSON/Document.php b/src/JSON/Document.php
index e4dd3d00753db5076d9d642b86445db00caa7078..a8137ef6cfdf047312b2ccb84e51c618c117c84b 100644
--- a/src/JSON/Document.php
+++ b/src/JSON/Document.php
@@ -131,11 +131,11 @@ class Document implements \ArrayAccess
      *
      * @return bool
      */
-    public static function comparePaths(string $a, string $b): bool
+    public static function comparePaths(string $left, string $right): bool
     {
-        $aParts = explode('/', $a);
-        $bParts = explode('/', $b);
+        $leftParts = explode('/', $left);
+        $rightParts = explode('/', $right);
 
-        return $aParts > $bParts;
+        return $leftParts > $rightParts;
     }
 }
diff --git a/src/Model/ArrayMetadata.php b/src/Model/ArrayMetadata.php
index b66abb4300a437a296246e5fa8098be897f87022..c5323734033e04f324e728f65d89442056cf3751 100644
--- a/src/Model/ArrayMetadata.php
+++ b/src/Model/ArrayMetadata.php
@@ -67,8 +67,8 @@ final class ArrayMetadata implements SimpleTypeInterface
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f(new self($this->item->fmap($f)));
+        return $func(new self($this->item->fmap($func)));
     }
 }
diff --git a/src/Model/BaseTypeMetadata.php b/src/Model/BaseTypeMetadata.php
index 146fc33f11ef49c3dc6bb944cc467e25e871dd60..ee65fd0e24e3fb3aa34d9d79922f8404fd1c4be6 100644
--- a/src/Model/BaseTypeMetadata.php
+++ b/src/Model/BaseTypeMetadata.php
@@ -56,8 +56,8 @@ final class BaseTypeMetadata implements SimpleTypeInterface
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f($this);
+        return $func($this);
     }
 }
diff --git a/src/Model/FormattedStringMetadata.php b/src/Model/FormattedStringMetadata.php
index 7788a5a5af97a2407d2180221a9e5f9d6f4650eb..6f91464d86981a9e73fc528bf0fd37e13ecc064e 100644
--- a/src/Model/FormattedStringMetadata.php
+++ b/src/Model/FormattedStringMetadata.php
@@ -54,8 +54,8 @@ class FormattedStringMetadata implements SimpleTypeInterface
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f($this);
+        return $func($this);
     }
 }
diff --git a/src/Model/MapMetadata.php b/src/Model/MapMetadata.php
index 76bea53bd39e3e8ee88fc248fdc130e0359747ec..2da5b75bbcc4f39a2ed4d8d29c754feaca1d1af3 100644
--- a/src/Model/MapMetadata.php
+++ b/src/Model/MapMetadata.php
@@ -67,8 +67,8 @@ final class MapMetadata implements SimpleTypeInterface
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f(new self($this->value->fmap($f)));
+        return $func(new self($this->value->fmap($func)));
     }
 }
diff --git a/src/Model/ObjectMetadata.php b/src/Model/ObjectMetadata.php
index 7fd6d7332829bad5e9f770d99afc6a8104db9d80..0a6fba6e04057f9cbae980d5b9e70c5c9072c389 100644
--- a/src/Model/ObjectMetadata.php
+++ b/src/Model/ObjectMetadata.php
@@ -103,12 +103,12 @@ class ObjectMetadata implements SimpleTypeInterface
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f(new self(
+        return $func(new self(
             $this->class,
-            TypeFunctorHelper::null($this->parent, $f),
-            TypeFunctorHelper::map($this->properties, $f)
+            TypeFunctorHelper::null($this->parent, $func),
+            TypeFunctorHelper::map($this->properties, $func)
         ));
     }
 }
diff --git a/src/Model/OperationMetadata.php b/src/Model/OperationMetadata.php
index 0bef36be458560ebf23fcbe2624f71817976b321..2b6948dff75f847cd63d3affe8c919b9cded18c7 100644
--- a/src/Model/OperationMetadata.php
+++ b/src/Model/OperationMetadata.php
@@ -135,14 +135,14 @@ final class OperationMetadata implements OperationIdentityInterface, TypeFunctor
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
         return new self(
             $this->id,
             $this->path,
             $this->method,
-            TypeFunctorHelper::null($this->input),
-            TypeFunctorHelper::null($this->output)
+            TypeFunctorHelper::null($this->input, $func),
+            TypeFunctorHelper::null($this->output, $func)
         );
     }
 }
diff --git a/src/Model/PropertyMetadata.php b/src/Model/PropertyMetadata.php
index ec220d5724f4800de0d9871da47ce028f60231ca..fd30b24ab210c44564fbbc783fa934f274d9db9a 100644
--- a/src/Model/PropertyMetadata.php
+++ b/src/Model/PropertyMetadata.php
@@ -149,11 +149,11 @@ final class PropertyMetadata implements TypeFunctor, PropertyAccessInterface
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
         return new self(
             $this->name,
-            $this->type->fmap($f),
+            $this->type->fmap($func),
             $this->nullable,
             $this->readable,
             $this->writable,
diff --git a/src/Model/Reference.php b/src/Model/Reference.php
index 494925ed8ef449ff046669cea8d1ab229e21fdb5..45454cfab11f0bacdac25f39f2e3a4e15ad51c15 100644
--- a/src/Model/Reference.php
+++ b/src/Model/Reference.php
@@ -82,12 +82,12 @@ class Reference implements TypeMetadata
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
         return new self(
             $this->id,
-            function () use ($f) {
-                return $this->getTarget()->fmap($f);
+            function () use ($func) {
+                return $this->getTarget()->fmap($func);
             }
         );
     }
diff --git a/src/Model/ResourceLinkMetadata.php b/src/Model/ResourceLinkMetadata.php
index 3e6cc2ecf4e9fb709dfcb8440d1252dc8d8cf130..3851e9a2c8c68d05387e5c0f9e31a690859498da 100644
--- a/src/Model/ResourceLinkMetadata.php
+++ b/src/Model/ResourceLinkMetadata.php
@@ -60,8 +60,8 @@ class ResourceLinkMetadata implements SimpleTypeInterface
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f(new self($this->target));
+        return $func(new self($this->target));
     }
 }
diff --git a/src/Model/ResourceMetadata.php b/src/Model/ResourceMetadata.php
index 16a857d723f1591a33752b93d9d114f945920e8d..92722fa360dae696a1888db408f050a3e19981c6 100644
--- a/src/Model/ResourceMetadata.php
+++ b/src/Model/ResourceMetadata.php
@@ -83,12 +83,12 @@ final class ResourceMetadata extends ObjectMetadata implements ResourceIdentityI
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f(new self(
+        return $func(new self(
             $this->id,
-            TypeFunctorHelper::null($this->getParent(), $f),
-            TypeFunctorHelper::map($this->getProperties(), $f),
+            TypeFunctorHelper::null($this->getParent(), $func),
+            TypeFunctorHelper::map($this->getProperties(), $func),
             $this->operations
         ));
     }
diff --git a/src/Model/TypeFunctor.php b/src/Model/TypeFunctor.php
index 93725a0c5b49e238b174a26ee49128ab148c12bf..02f1bacd89ee48c947217f14a920e2439bdce1f9 100644
--- a/src/Model/TypeFunctor.php
+++ b/src/Model/TypeFunctor.php
@@ -26,9 +26,9 @@ namespace Irstea\ApiMetadata\Model;
 interface TypeFunctor
 {
     /**
-     * @param callable $f
+     * @param callable $func
      *
      * @return $this
      */
-    public function fmap(callable $f);
+    public function fmap(callable $func);
 }
diff --git a/src/Model/UnionTypeMetadata.php b/src/Model/UnionTypeMetadata.php
index 5c23cc72c03073fde87e0b91fc5a5dec99729d50..09a0f9e8057932d9f517910ca459b25780a97dee 100644
--- a/src/Model/UnionTypeMetadata.php
+++ b/src/Model/UnionTypeMetadata.php
@@ -58,8 +58,8 @@ class UnionTypeMetadata implements TypeMetadata
     /**
      * {@inheritdoc}
      */
-    public function fmap(callable $f)
+    public function fmap(callable $func)
     {
-        return $f(new self(TypeFunctorHelper::map($this->alternatives, $f)));
+        return $func(new self(TypeFunctorHelper::map($this->alternatives, $func)));
     }
 }
diff --git a/tests/Fixtures/Controller/PasswordChangeController.php b/tests/Fixtures/Controller/PasswordChangeController.php
index 8d4fe17c8b99da7f0091ab3a787c7fbafed9e0fc..5cd232c79c154dca51e8b3a702b3d0fa0c22fb12 100644
--- a/tests/Fixtures/Controller/PasswordChangeController.php
+++ b/tests/Fixtures/Controller/PasswordChangeController.php
@@ -21,8 +21,8 @@
 namespace Irstea\ApiMetadata\Tests\Fixtures\Controller;
 
 use Doctrine\ORM\EntityManagerInterface;
+use Irstea\ApiMetadata\Tests\Fixtures\Entity\LocalUser;
 use Irstea\ApiMetadata\Tests\Fixtures\Entity\PasswordChangeRequest;
-use Irstea\ApiMetadata\Tests\Fixtures\Entity\User;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
@@ -61,12 +61,12 @@ class PasswordChangeController
     }
 
     /**
-     * @param Request $req
-     * @param User    $data
+     * @param Request   $req
+     * @param LocalUser $data
      *
      * @return Response
      */
-    public function __invoke(Request $req, User $data): Response
+    public function __invoke(Request $req, LocalUser $data): Response
     {
         /** @var PasswordChangeRequest $dto */
         $dto = $this->serializer->deserialize($req->getContent(), PasswordChangeRequest::class, 'json');
diff --git a/tests/Fixtures/Entity/ExternalUser.php b/tests/Fixtures/Entity/ExternalUser.php
new file mode 100644
index 0000000000000000000000000000000000000000..c832bda7b72498d3acb10459fcbc501fdd0e5cd0
--- /dev/null
+++ b/tests/Fixtures/Entity/ExternalUser.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of "irstea/api-metadata".
+ *
+ * Copyright (C) 2019 IRSTEA
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License and the GNU
+ * Lesser General Public License along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+namespace Irstea\ApiMetadata\Tests\Fixtures\Entity;
+
+use ApiPlatform\Core\Annotation as API;
+use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Class ExternalUser.
+ *
+ * @ORM\Entity
+ * @API\ApiResource(itemOperations={"get"}, collectionOperations={})
+ */
+class ExternalUser extends User
+{
+    /**
+     * @var string
+     * @ORM\Column(type="string")
+     * @Assert\NotBlank()
+     */
+    private $externalReference;
+
+    /**
+     * Get externalReference.
+     *
+     * @return string
+     */
+    public function getExternalReference(): string
+    {
+        return $this->externalReference;
+    }
+
+    /**
+     * Set externalReference.
+     *
+     * @param string $externalReference
+     */
+    public function setExternalReference(string $externalReference): void
+    {
+        $this->externalReference = $externalReference;
+    }
+}
diff --git a/tests/Fixtures/Entity/LocalUser.php b/tests/Fixtures/Entity/LocalUser.php
new file mode 100644
index 0000000000000000000000000000000000000000..5488ed416ba611bfa17f5204399af93e9a7f7093
--- /dev/null
+++ b/tests/Fixtures/Entity/LocalUser.php
@@ -0,0 +1,79 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of "irstea/api-metadata".
+ *
+ * Copyright (C) 2019 IRSTEA
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License and the GNU
+ * Lesser General Public License along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+namespace Irstea\ApiMetadata\Tests\Fixtures\Entity;
+
+use ApiPlatform\Core\Annotation as API;
+use Assert\Assertion;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Class LocalUser.
+ *
+ * @ORM\Entity
+ * @API\ApiResource(
+ *     itemOperations={
+ *         "get",
+ *         "put",
+ *         "password"={
+ *             "method": "POST",
+ *             "path": "/users/{id}/password",
+ *             "controller"=PasswordChangeController::class,
+ *             "input"=PasswordChangeRequest::class,
+ *             "output"=false
+ *         },
+ *     },
+ *     collectionOperations={
+ *          "get"
+ *     }
+ * )
+ */
+class LocalUser extends User
+{
+    /**
+     * @var string|null
+     * @ORM\Column(type="string", nullable=true)
+     * @API\ApiProperty(readable=false, writable=false)
+     */
+    private $password;
+
+    /**
+     * @param string $password
+     *
+     * @return bool
+     */
+    public function checkPassword(string $password): bool
+    {
+        return $this->password !== null ? \password_verify($password, $this->password) : $password === '';
+    }
+
+    /**
+     * @param PasswordChangeRequest $req
+     */
+    public function changePassword(PasswordChangeRequest $req): void
+    {
+        if (!$this->checkPassword($req->getOld())) {
+            throw new \InvalidArgumentException('Old passwords mismatch');
+        }
+        $hash = \password_hash($req->getNew(), \PASSWORD_DEFAULT);
+        Assertion::string($hash, 'could not hash password');
+        $this->password = $hash;
+    }
+}
diff --git a/tests/Fixtures/Entity/User.php b/tests/Fixtures/Entity/User.php
index f0517e9930b376b80b77ddd168bd6e36925565bc..0cdad7eb2df53beb2f3e6f2484eff09521f479d6 100644
--- a/tests/Fixtures/Entity/User.php
+++ b/tests/Fixtures/Entity/User.php
@@ -21,9 +21,7 @@
 namespace Irstea\ApiMetadata\Tests\Fixtures\Entity;
 
 use ApiPlatform\Core\Annotation as API;
-use Assert\Assertion;
 use Doctrine\ORM\Mapping as ORM;
-use Irstea\ApiMetadata\Tests\Fixtures\Controller\PasswordChangeController;
 use Ramsey\Uuid\Uuid;
 use Ramsey\Uuid\UuidInterface;
 use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
@@ -33,20 +31,9 @@ use Symfony\Component\Validator\Constraints as Assert;
  * Class User.
  *
  * @ORM\Entity
- * @API\ApiResource(
- *     itemOperations={
- *         "get",
- *         "put",
- *         "password"={
- *             "method": "POST",
- *             "path": "/users/{id}/password",
- *             "controller"=PasswordChangeController::class,
- *             "input"=PasswordChangeRequest::class,
- *             "output"=false
- *         },
- *     },
- *     collectionOperations={"get"}
- * )
+ * @ORM\InheritanceType("SINGLE_TABLE")
+ * @ORM\DiscriminatorColumn("type")
+ * @API\ApiResource(itemOperations={"get"}, collectionOperations={})
  * @UniqueEntity(fields={"login"}, ignoreNull=true)
  */
 class User
@@ -65,13 +52,6 @@ class User
      */
     private $login;
 
-    /**
-     * @var string|null
-     * @ORM\Column(type="string", nullable=true)
-     * @API\ApiProperty(readable=false, writable=false)
-     */
-    private $password;
-
     /**
      * @var Person|null
      * @ORM\OneToOne(targetEntity=Person::class, inversedBy="user", cascade={"persist"}, orphanRemoval=true)
@@ -136,27 +116,4 @@ class User
             $person->setUser($this);
         }
     }
-
-    /**
-     * @param string $password
-     *
-     * @return bool
-     */
-    public function checkPassword(string $password): bool
-    {
-        return $this->password !== null ? \password_verify($password, $this->password) : $password === '';
-    }
-
-    /**
-     * @param PasswordChangeRequest $req
-     */
-    public function changePassword(PasswordChangeRequest $req): void
-    {
-        if (!$this->checkPassword($req->getOld())) {
-            throw new \InvalidArgumentException('Old passwords mismatch');
-        }
-        $hash = \password_hash($req->getNew(), \PASSWORD_DEFAULT);
-        Assertion::string($hash, 'could not hash password');
-        $this->password = $hash;
-    }
 }