public function getRoutes()
    {
        if (!$this->sorted)
            $this->sortModules();

        $cache = $this->getCachedData();

        if ($cache !== null && $this->root === null)
        {
            $root = $cache->get('data');
            if ($root instanceof Route)
            {
                $this->root = $root;
                $this->root_search_path = $cache->get('search_path');
            }
        }

        if ($this->root !== null)
            return $this->root;
        
        $this->root = new Route('/', 0);
        $this->root_search_path = $this->search_path;
        foreach ($this->search_path as $module => $info)
        {
            $app_path = $info['path'];
            $files = self::listDir($app_path);
            foreach ($files as $path)
            {
                $file = str_replace($app_path, "", $path);
                $parts = array_filter(explode("/", $file));
                $ptr = $this->root;

                $cnt = 0;
                $l = count($parts);
                foreach ($parts as $part)
                {
                    $last = $cnt === $l - 1;
                    if ($last)
                    {
                        if ($part === "index.php")
                        {
                            // Only store if empty - 
                            $ptr->addApp($path, '', $module);
                        }
                        else
                        {
                            $app_name = substr($part, 0, -4);

                            // Strip file extension
                            $ext = "";
                            $ext_pos = strrpos($app_name, '.');
                            if (!empty($ext_pos))
                            {
                                $ext = substr($app_name, $ext_pos);
                                $app_name = substr($app_name, 0, $ext_pos);
                            }

                            $app = $ptr->getSubRoute($app_name);
                            $app->addApp($path, $ext, $module);
                        }
                        break;
                    }
                
                    // Move the pointer deeper
                    $ptr = $ptr->getSubRoute($part);
                    ++$cnt;
                }
            }
        }

        if ($cache !== null)
            $cache->set('data', $this->root);

        return $this->root;
    }