/**
  * Process one single library definition resolving referenced dependencies.
  *
  * @param LibraryDefinitionInterface $definition Library definition to process.
  * @param ContainerInterface $container Container which is subject of process.
  * @param array $processedDefinitions List of already processed definitions.
  * @param int $count Number of processed definition for detecting circular references.
  * @throws CircularReferenceException If circular reference is detected.
  */
 private function processDefinition(LibraryDefinitionInterface $definition, ContainerInterface $container, array &$processedDefinitions, &$count = 0)
 {
     $count++;
     if ($count > count($container->getLibraries()->getDefinitions())) {
         throw new CircularReferenceException('Circular reference detected.');
     }
     /**
      * @var ResourceInterface $resource
      */
     foreach ($resources = $definition->getResources() as $resource) {
         /**
          * @var ReferenceResource $resource
          */
         if ($resource instanceof ReferenceResource) {
             if (!isset($processedDefinitions[$resource->getSource()])) {
                 $this->processDefinition($container->getLibraries()->getDefinition($resource->getSource()), $container, $processedDefinitions, $count);
             }
             $definition->replaceResource($resource, array_filter($this->getReferencedResources($resource, $container), function (ResourceInterface $replacement) use($definition) {
                 return !in_array($replacement, $definition->getResources());
             }));
         }
     }
     $processedDefinitions[$definition->getName()] = $definition->getName();
 }
 /**
  * Checks for circular references within the definitions in ContainerInterface using recursive function and
  * pointer to processed definitions list.
  *
  * @param ContainerInterface $container Container to check.
  * @param LibraryDefinitionInterface $definition Library definition to process.
  * @param array $registeredReferences List of already processed definitions in path.
  * @throws CircularReferenceException If circular reference is detected.
  */
 private function doCheckCircularReferences(ContainerInterface $container, LibraryDefinitionInterface $definition, array $registeredReferences)
 {
     /**
      * @var ResourceInterface $resource
      */
     foreach ($resources = $definition->getResources() as $resource) {
         /**
          * @var ReferenceResource $resource
          */
         if ($resource instanceof ReferenceResource) {
             if (array_key_exists($resource->getSource(), $registeredReferences)) {
                 throw new CircularReferenceException(sprintf('Circular reference detected at definition "%s", dependency chain (path: [%s] => [%s]).', $resource->getSource(), implode('] => [', $registeredReferences), $resource->getSource()));
             } else {
                 $newPath = $registeredReferences;
                 $newPath[$resource->getSource()] = $resource->getSource();
                 $this->doCheckCircularReferences($container, $container->getLibraries()->getDefinition($resource->getSource()), $newPath);
             }
         }
     }
 }
 /**
  * Check if definition does not have any resource.
  *
  * @param ContainerInterface $container Current container.
  * @param LibraryDefinitionInterface $definition Current definition.
  */
 private function checkIsDefinitionEmpty(ContainerInterface $container, LibraryDefinitionInterface $definition)
 {
     if (count($definition->getResources()) == 0) {
         throw new InvalidArgumentException(sprintf('Library definition "%s" does not contain any resource.', $definition->getName()));
     }
 }