public function testValueObject()
 {
     $type = new Type(Type::BUILTIN_TYPE_STRING);
     $metadata = new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'desc', true, true, false, false, true, false, 'http://example.com/foo', null, ['foo' => 'bar']);
     $this->assertEquals($type, $metadata->getType());
     $this->assertEquals('desc', $metadata->getDescription());
     $this->assertTrue($metadata->isReadable());
     $this->assertTrue($metadata->isWritable());
     $this->assertFalse($metadata->isReadableLink());
     $this->assertFalse($metadata->isWritableLink());
     $this->assertTrue($metadata->isRequired());
     $this->assertFalse($metadata->isIdentifier());
     $this->assertEquals('http://example.com/foo', $metadata->getIri());
     $this->assertEquals(['foo' => 'bar'], $metadata->getAttributes());
     $newType = new Type(Type::BUILTIN_TYPE_BOOL);
     $newMetadata = $metadata->withType($newType);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertEquals($newType, $newMetadata->getType());
     $newMetadata = $metadata->withDescription('description');
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertEquals('description', $newMetadata->getDescription());
     $newMetadata = $metadata->withReadable(false);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertFalse($newMetadata->isReadable());
     $newMetadata = $metadata->withWritable(false);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertFalse($newMetadata->isWritable());
     $newMetadata = $metadata->withReadableLink(true);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertTrue($newMetadata->isReadableLink());
     $newMetadata = $metadata->withWritableLink(true);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertTrue($newMetadata->isWritableLink());
     $newMetadata = $metadata->withRequired(false);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertFalse($newMetadata->isRequired());
     $newMetadata = $metadata->withIdentifier(true);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertTrue($newMetadata->isIdentifier());
     $newMetadata = $metadata->withIri('foo:bar');
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertEquals('foo:bar', $newMetadata->getIri());
     $newMetadata = $metadata->withAttributes(['a' => 'b']);
     $this->assertNotSame($metadata, $newMetadata);
     $this->assertEquals(['a' => 'b'], $newMetadata->getAttributes());
 }
 /**
  * Gets a property definition.
  *
  * @param PropertyMetadata $propertyMetadata
  * @param string           $propertyName
  * @param string           $prefixedShortName
  * @param string           $shortName
  *
  * @return array
  */
 private function getProperty(PropertyMetadata $propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName) : array
 {
     $type = $propertyMetadata->isReadableLink() ? 'rdf:Property' : 'hydra:Link';
     $property = ['@type' => 'hydra:SupportedProperty', 'hydra:property' => ['@id' => ($iri = $propertyMetadata->getIri()) ? $iri : sprintf('#%s/%s', $shortName, $propertyName), '@type' => $type, 'rdfs:label' => $propertyName, 'domain' => $prefixedShortName], 'hydra:title' => $propertyName, 'hydra:required' => $propertyMetadata->isRequired(), 'hydra:readable' => $propertyMetadata->isReadable(), 'hydra:writable' => $propertyMetadata->isWritable()];
     if (null !== ($range = $this->getRange($propertyMetadata))) {
         $property['hydra:property']['range'] = $range;
     }
     if (null !== ($description = $propertyMetadata->getDescription())) {
         $property['hydra:description'] = $description;
     }
     return $property;
 }
 /**
  * Gets a property Schema Object.
  *
  * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject
  *
  * @param PropertyMetadata $propertyMetadata
  *
  * @return \ArrayObject
  */
 private function getPropertySchema(PropertyMetadata $propertyMetadata) : \ArrayObject
 {
     $propertySchema = new \ArrayObject();
     if (false === $propertyMetadata->isWritable()) {
         $propertySchema['readOnly'] = true;
     }
     if (null !== ($description = $propertyMetadata->getDescription())) {
         $propertySchema['description'] = $description;
     }
     if (null === ($type = $propertyMetadata->getType())) {
         return $propertySchema;
     }
     $isCollection = $type->isCollection();
     if (null === ($valueType = $isCollection ? $type->getCollectionValueType() : $type)) {
         $builtinType = 'string';
         $className = null;
     } else {
         $builtinType = $valueType->getBuiltinType();
         $className = $valueType->getClassName();
     }
     $valueSchema = $this->getType($builtinType, $isCollection, $className, $propertyMetadata->isReadableLink());
     return new \ArrayObject((array) $propertySchema + $valueSchema);
 }
 /**
  * Normalizes a relation as an URI if is a Link or as a JSON-LD object.
  *
  * @param PropertyMetadata $propertyMetadata
  * @param mixed            $relatedObject
  * @param string           $resourceClass
  * @param string|null      $format
  * @param array            $context
  *
  * @return string|array
  */
 private function normalizeRelation(PropertyMetadata $propertyMetadata, $relatedObject, string $resourceClass, string $format = null, array $context)
 {
     if ($propertyMetadata->isReadableLink()) {
         return $this->serializer->normalize($relatedObject, $format, $this->createRelationSerializationContext($resourceClass, $context));
     }
     return $this->iriConverter->getIriFromItem($relatedObject);
 }