public function locateResource($name, $dir = null, $first = true)
    {
        if ('@' !== $name[0]) {
            throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
        }

        if (false !== strpos($name, '..')) {
            throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
        }
        $moduleName = substr($name, 1);
        $path       = '';
        if (false !== strpos($moduleName, '/')) {
            list($moduleName, $path) = explode('/', $moduleName, 2);
        }

        $isResource     = 0 === strpos($path, 'Resources') && null !== $dir;
        $overridePath   = substr($path, 9);
        $resourceModule = null;
        $modules        = array($this->getModule($moduleName));
        $files          = array();

        foreach ($modules as $module) {
            if ($isResource && file_exists($file = $dir . '/' . $module->getName() . $overridePath)) {
                if (null !== $resourceModule) {
                    throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived module. Create a "%s" file to override the module resource.',
                        $file,
                        $resourceModule,
                        $dir . '/' . $modules[0]->getName() . $overridePath
                    ));
                }

                if ($first) {
                    return $file;
                }
                $files[] = $file;
            }

            if (file_exists($file = $this->getResourcesPath($module) . '/' . $path)) {
                if ($first && !$isResource) {
                    return $file;
                }
                $files[]        = $file;
                $resourceModule = $module->getName();
            }
        }

        if (count($files) > 0) {
            return $first && $isResource ? $files[0] : $files;
        }

        throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
    }