@param InterfaceToCall|null $relatedClassInterface
@param array $parameterConverterAnnotations

@return array
@throws \SimplyCodedSoftware\Messaging\MessagingException
@throws \SimplyCodedSoftware\Messaging\Support\InvalidArgumentException
960048
public function createParameterConverters(?InterfaceToCall $relatedClassInterface, array $parameterConverterAnnotations): array
    {
        $parameterConverters = [];

        foreach ($parameterConverterAnnotations as $parameterConverterAnnotation) {
            if ($parameterConverterAnnotation instanceof Header) {
                if ($parameterConverterAnnotation->isRequired) {
                    $parameterConverters[] = HeaderBuilder::create($parameterConverterAnnotation->parameterName, $parameterConverterAnnotation->headerName);
                } else {
                    $parameterConverters[] = HeaderBuilder::createOptional($parameterConverterAnnotation->parameterName, $parameterConverterAnnotation->headerName);
                }
            } else if ($parameterConverterAnnotation instanceof Payload) {
                $parameterConverters[] = PayloadBuilder::create($parameterConverterAnnotation->parameterName);
            } else if ($parameterConverterAnnotation instanceof MessageParameter) {
                $parameterConverters[] = MessageConverterBuilder::create($parameterConverterAnnotation->parameterName);
            } else if ($parameterConverterAnnotation instanceof Reference) {
                if ($parameterConverterAnnotation->referenceName) {
                    $parameterConverters[] = ReferenceBuilder::create($parameterConverterAnnotation->parameterName, $parameterConverterAnnotation->referenceName);
                }elseif ($relatedClassInterface) {
                    $parameterConverters[] = ReferenceBuilder::createFromParameterTypeHint($parameterConverterAnnotation->parameterName, $relatedClassInterface);
                }else {
                    $parameterConverters[] = ReferenceBuilder::createWithDynamicResolve($parameterConverterAnnotation->parameterName);
                }
            } else if ($parameterConverterAnnotation instanceof Expression) {
                $parameterConverters[] = ExpressionBuilder::create(
                    $parameterConverterAnnotation->parameterName, $parameterConverterAnnotation->expression
                );
            } else if ($parameterConverterAnnotation instanceof Value) {
                $parameterConverters[] = ValueBuilder::create($parameterConverterAnnotation->parameterName, $parameterConverterAnnotation->value);
            }
        }

        return $parameterConverters;
    }
715987
protected function normalizeRelation(PropertyMetadata $propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context)
    {
        if (null === $relatedObject || !empty($context['attributes']) || $propertyMetadata->isReadableLink()) {
            if (null === $relatedObject) {
                unset($context['resource_class']);
            } else {
                $context['resource_class'] = $resourceClass;
            }

            if (!$this->serializer instanceof NormalizerInterface) {
                throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', NormalizerInterface::class));
            }

            return $this->serializer->normalize($relatedObject, $format, $context);
        }

        $iri = $this->iriConverter->getIriFromItem($relatedObject);
        if (isset($context['resources'])) {
            $context['resources'][$iri] = $iri;
        }
        if (isset($context['resources_to_push']) && $propertyMetadata->getAttribute('push', false)) {
            $context['resources_to_push'][$iri] = $iri;
        }

        return $iri;
    }
532681
private static function parseParameters(array $parametersArray): ParameterCollectionInterface
    {
        $parameters = new ParameterCollection();

        foreach ($parametersArray as $parameterName => $parameterValue) {
            $parameters->set(
                strval($parameterName),
                strval(is_array($parameterValue) ? $parameterValue[0] : $parameterValue)
            );
        }

        return $parameters;
    }
840297
protected function normalizeRelation(PropertyMetadata $propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context)
    {
        if (null === $relatedObject) {
            if (isset($context['operation_type'], $context['subresource_resources'][$resourceClass]) && OperationType::SUBRESOURCE === $context['operation_type']) {
                $iri = $this->iriConverter->getItemIriFromResourceClass($resourceClass, $context['subresource_resources'][$resourceClass]);
            } else {
                unset($context['resource_class']);

                if ($this->serializer instanceof NormalizerInterface) {
                    return $this->serializer->normalize($relatedObject, $format, $context);
                }
                throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', NormalizerInterface::class));
            }
        } else {
            $iri = $this->iriConverter->getIriFromItem($relatedObject);
            $context['iri'] = $iri;

            if (isset($context['resources'])) {
                $context['resources'][$iri] = $iri;
            }
            if (isset($context['api_included'])) {
                if (!$this->serializer instanceof NormalizerInterface) {
                    throw new LogicException(sprintf('The injected serializer must be an instance of "%s".', NormalizerInterface::class));
                }

                return $this->serializer->normalize($relatedObject, $format, $context);
            }
        }

        return [
            'data' => [
                'type' => $this->resourceMetadataFactory->create($resourceClass)->getShortName(),
                'id' => $iri,
            ],
        ];
    }
86233
public function getSkillRelatedByParentId(ConnectionInterface $con = null)
    {
        if ($this->aSkillRelatedByParentId === null && ($this->parent_id !== null)) {
            $this->aSkillRelatedByParentId = ChildSkillQuery::create()->findPk($this->parent_id, $con);
            /* The following can be used additionally to
                guarantee the related object contains a reference
                to this object.  This level of coupling may, however, be
                undesirable since it could result in an only partially populated collection
                in the referenced object.
                $this->aSkillRelatedByParentId->addParents($this);
             */
        }

        return $this->aSkillRelatedByParentId;
    }
669228
public function getSkillRelatedByDependencyId(ConnectionInterface $con = null)
    {
        if ($this->aSkillRelatedByDependencyId === null && ($this->dependency_id !== null)) {
            $this->aSkillRelatedByDependencyId = ChildSkillQuery::create()->findPk($this->dependency_id, $con);
            /* The following can be used additionally to
                guarantee the related object contains a reference
                to this object.  This level of coupling may, however, be
                undesirable since it could result in an only partially populated collection
                in the referenced object.
                $this->aSkillRelatedByDependencyId->addChildren($this);
             */
        }

        return $this->aSkillRelatedByDependencyId;
    }
1059988
protected function getDependencies($parameters)
	{
		$dependencies = array();

		foreach ($parameters as $parameter)
		{
			$dependency = $parameter->getClass();

			// If the class is null, it means the dependency is a string or some other
			// primitive type which we can not resolve since it is not a class and
			// we'll just bomb out with an error since we have no-where to go.
			if (is_null($dependency))
			{
				$dependencies[] = $this->resolveNonClass($parameter);
			}
			else
			{
				$dependencies[] = $this->resolveClass($parameter);
			}
		}

		return (array) $dependencies;
	}
472594
protected function tlsStreamInitializer(ParametersInterface $parameters)
    {
        $resource = $this->tcpStreamInitializer($parameters);
        $metadata = stream_get_meta_data($resource);

        // Detect if crypto mode is already enabled for this stream (PHP >= 7.0.0).
        if (isset($metadata['crypto'])) {
            return $resource;
        }

        if (is_array($parameters->ssl)) {
            $options = $parameters->ssl;
        } else {
            $options = array();
        }

        if (!isset($options['crypto_type'])) {
            $options['crypto_type'] = STREAM_CRYPTO_METHOD_TLS_CLIENT;
        }

        if (!stream_context_set_option($resource, array('ssl' => $options))) {
            $this->onConnectionError('Error while setting SSL context options');
        }

        if (!stream_socket_enable_crypto($resource, true, $options['crypto_type'])) {
            $this->onConnectionError('Error while switching to encrypted communication');
        }

        return $resource;
    }
687234
private function getDependencyInjectionParameters(array $reflectionParameters, array $arguments = []): array
    {
        $parameters = [];

        // Treat arguments
        $argumentsClass = [];
        foreach ($arguments as $name => &$argument) {
            if (!is_null($this->getContainer())) {
                // Service recursively
                if (is_string($argument) && substr($argument, 0, 1) == '@') {
                    $subServiceName = substr($argument, 1);
                    $argument = $this->getContainer()->get($subServiceName);
                }
            }

            // Get all classes of argument if it's an object.
            // It's necessary to know if argument can match with an injection.
            if (is_object($argument) && !($argument instanceof \stdClass)) {
                foreach ($this->getClassIndex()->getAllClasses($argument) as $class) {
                    $argumentsClass[$class][] = $name;
                }
            }
        }

        // Try to get all parameters values
        foreach ($reflectionParameters as $reflectionParameter) {
            if ($reflectionParameter instanceof \ReflectionParameter) {
                $parameters[$reflectionParameter->getName()] =
                    $this->getDependencyInjectionParameter($reflectionParameter,
                                                           $arguments,
                                                           $argumentsClass);
            }
        }

        return $parameters;
    }
39785
public static function getMethodAnnotations($className, $methodName, $annotationClassName = null)
    {
        if(!isset(static::$annotations[$className]['Methods'][$methodName]))
        {
            return [];
        }
        if(null === $annotationClassName)
        {
            return static::$annotations[$className]['Methods'][$methodName];
        }
        else
        {
            $result = [];
            foreach(static::$annotations[$className]['Methods'][$methodName] as $annotation)
            {
                if($annotation instanceof $annotationClassName)
                {
                    $result[] = $annotation;
                }
            }
            return $result;
        }
    }
927532
protected function codeIssueToken(array $parameters, ClientInterface $determinedClient = null): ResponseInterface
    {
        // client_id is required @link https://tools.ietf.org/html/rfc6749#section-4.1.3
        if ($determinedClient === null || $determinedClient->isCodeGrantEnabled() === false) {
            throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_UNAUTHORIZED_CLIENT);
        }

        if (($codeValue = $this->codeGetCode($parameters)) === null ||
            ($code = $this->codeGetIntegration()->codeReadAuthenticationCode($codeValue)) === null
        ) {
            throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_INVALID_GRANT);
        }

        if ($code->hasBeenUsedEarlier() === true) {
            $this->codeGetIntegration()->codeRevokeTokens($code);
            throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_INVALID_GRANT);
        }

        if ($code->getClientIdentifier() !== $determinedClient->getIdentifier()) {
            throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_UNAUTHORIZED_CLIENT);
        }

        if ($code->getRedirectUriString() !== null) {
            // REQUIRED, if the "redirect_uri" parameter was included in the authorization request
            if (($redirectUri = $this->codeGetRedirectUri($parameters)) === null ||
                $redirectUri !== $code->getRedirectUriString()
            ) {
                throw new OAuthTokenBodyException(OAuthTokenBodyException::ERROR_INVALID_GRANT);
            }
        }

        $response = $this->codeGetIntegration()->codeCreateAccessTokenResponse($code, $parameters);

        return $response;
    }
716391
protected function getRelationStatement($thisAttr, $parameters,
          array $otherObjectProxies, $otherRole,
          $criteria=null, $orderby=null, PagingInfo $pagingInfo=null) {
    $queryId = $this->getCacheKey($otherRole.sizeof($otherObjectProxies), null, $criteria, $orderby, $pagingInfo);
    $tableName = $this->getRealTableName();
    $selectStmt = SelectStatement::get($this, $queryId);
    if (!$selectStmt->isCached()) {
      // initialize the statement
      $selectStmt->from($tableName, '');
      $this->addColumns($selectStmt, $tableName);
      $selectStmt->where($this->quoteIdentifier($tableName).'.'.
              $this->quoteIdentifier($thisAttr->getColumn()).' IN('.join(',', array_keys($parameters)).')');
      // order
      $this->addOrderBy($selectStmt, $orderby, $this->getType(), $tableName, $this->getDefaultOrder($otherRole));
      // additional conditions
      $parameters = array_merge($parameters, $this->addCriteria($selectStmt, $criteria, $tableName));
      // limit
      if ($pagingInfo != null) {
        $selectStmt->limit($pagingInfo->getPageSize());
      }
    }
    else {
      // on used statements only set parameters
      $parameters = array_merge($parameters, $this->getParameters($criteria, $tableName));
    }

    // set parameters
    $selectStmt->setParameters($parameters);

    // always update offset, since it's most likely not contained in the cache id
    if ($pagingInfo != null) {
      $selectStmt->offset($pagingInfo->getOffset());
    }
    return $selectStmt;
  }
433104
private static function loadDependency($parameterClass) {
		if (!isset(self::$instance[$parameterClass])) {
			/** @var DependencyManager $parameterDependency */
			$parameterDependency = $parameterClass;

			self::$loading[$parameterClass] = true;
			self::$instance[$parameterClass] = $parameterDependency::init();
		}

		return self::$instance[$parameterClass];
	}
1060167
private function extractMessageClass(array $parameters): string
    {
        if (0 === \count($parameters))
        {
            throw InvalidHandlerArguments::emptyArguments();
        }

        /** @var \ReflectionParameter $firstArgument */
        $firstArgument = $parameters[0];

        if (null !== $firstArgument->getType())
        {
            /** @var \ReflectionType $type */
            $type = $firstArgument->getType();

            /** @psalm-var class-string $className */
            $className = $type->getName();

            /** @psalm-suppress RedundantConditionGivenDocblockType */
            if (true === \class_exists($className))
            {
                return $className;
            }
        }

        throw InvalidHandlerArguments::invalidFirstArgument();
    }
368088
private function convertClassAnnotationsToClassMetadata(
        array $classAnnotations,
        ReflectionClass $reflectionClass,
        Mapping\ClassMetadata $parent
    ) {
        switch (true) {
            case isset($classAnnotations[Annotation\Entity::class]):
                return $this->convertClassAnnotationsToEntityClassMetadata(
                    $classAnnotations,
                    $reflectionClass,
                    $parent
                );

                break;

            case isset($classAnnotations[Annotation\MappedSuperclass::class]):
                return $this->convertClassAnnotationsToMappedSuperClassMetadata(
                    $classAnnotations,
                    $reflectionClass,
                    $parent
                );
            case isset($classAnnotations[Annotation\Embeddable::class]):
                return $this->convertClassAnnotationsToEntityClassMetadata(
                    $classAnnotations,
                    $reflectionClass,
                    $parent
                );
            default:
                throw Mapping\MappingException::classIsNotAValidEntityOrMappedSuperClass($reflectionClass->getName());
        }
    }
83586
protected function transformDependency(ReflectionParameter $parameter, $parameters)
    {
        // Get owner class
        $class = $parameter->getClass();

        // We skip parameters with a type hint to avoid replacing model bindings
        if ($class && !$this->alreadyInParameters($class->name, $parameters)) {
            return $this->container->make($class->name);
        }

        return null;
    }
658839
public function relatedToOne(
        string $otherClass,
        array $fieldsMap,
        bool $applySetters = false
    ) {
        //@TODO remove duplicated code

        $thisValues = array_intersect_key($this->data, $fieldsMap);

        $filterFn = function (Query $query) use (&$thisValues, &$fieldsMap) {
            $query->where(function (WhereClause $where) use (&$query, &$thisValues, &$fieldsMap) {
                foreach ($fieldsMap as $thisKey => $thatKey) {
                    $where->and($thatKey, '=', '?');
                    $query->bind($thisValues[$thisKey]);
                }
            });

            $query->limit(1);
        };

        /* @var $otherClass Model */
        $search = $otherClass::find($filterFn, $applySetters);

        return !(empty($search)) ? $search[0] : null;
    }