/**
  * Generates a URL from the given node or returns false if unable.
  *
  * @param string|Descriptor\PackageDescriptor $node
  *
  * @return string|false
  */
 public function __invoke($node)
 {
     $converter = new QualifiedNameToUrlConverter();
     return '/packages/' . $converter->fromPackage($node->getFullyQualifiedStructuralElementName()) . '.html';
 }
 /**
  * Creates a tree of PackageDescriptors based on the provided FQNN (package name).
  *
  * This method will examine the package name and create a package descriptor for each part of
  * the FQNN if it doesn't exist in the packages field of the current package (starting with the root
  * Package in the Project Descriptor),
  *
  * As an intended side effect this method also populates the *elements* index of the ProjectDescriptor with all
  * created PackageDescriptors. Each index key is prefixed with a tilde (~) so that it will not conflict with
  * other FQSEN's, such as classes or interfaces.
  *
  * @param ProjectDescriptor $project
  * @param string            $packageName A FQNN of the package (and parents) to create.
  *
  * @see ProjectDescriptor::getPackage() for the root package.
  * @see PackageDescriptor::getChildren() for the child packages of a given package.
  *
  * @return void
  */
 protected function createPackageDescriptorTree(ProjectDescriptor $project, $packageName)
 {
     $parts = explode('\\', ltrim($packageName, '\\'));
     $fqnn = '';
     // this method does not use recursion to traverse the tree but uses a pointer that will be overridden with the
     // next item that is to be traversed (child package) at the end of the loop.
     /** @var PackageDescriptor $pointer  */
     $pointer = $project->getIndexes()->packages['\\'];
     foreach ($parts as $part) {
         $fqnn .= '\\' . $part;
         if ($pointer->getChildren()->get($part)) {
             $pointer = $pointer->getChildren()->get($part);
             continue;
         }
         // package does not exist, create it
         $interimPackageDescriptor = new PackageDescriptor();
         $interimPackageDescriptor->setParent($pointer);
         $interimPackageDescriptor->setName($part);
         $interimPackageDescriptor->setFullyQualifiedStructuralElementName($fqnn);
         // add to the pointer's list of children
         $pointer->getChildren()->set($part ?: 'UNKNOWN', $interimPackageDescriptor);
         // add to index
         $project->getIndexes()->packages[$fqnn] = $interimPackageDescriptor;
         // move pointer forward
         $pointer = $interimPackageDescriptor;
     }
 }