/// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        public ReadOnlyCollection <FileInfo> GetAllFilesFrom(string path)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(path, "path");

            try
            {
                var nodeResolvingResult = this.ResolveFolderNodeByPath(path);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                return(this.GetAllFilesFrom(parentFolder).Select(file => new FileInfo(file, _pathBuilder.CombinePaths(path, file.Name))).ToList().AsReadOnly());
            }
            catch (InvalidPathException exception)
            {
                throw new FolderNotFoundException("Не удалось получить файлы, содержащиеся в папке \"{0}\". {1}".FormatWith(path, exception.Message));
            }
        }
        /// <exception cref="FileNotFoundException"></exception>
        internal FileNode ResolveFileNode(
            string filePath,
            NodeResolvingResult <FolderNode> parentFolderResolvingResult,
            string fileName,
            string verbForPuttingIntoExceptionMessageTemplate,
            out ReadOnlyCollection <FileNode> filesFromSameFolder)
        {
            FolderNode folderToRemoveFileFrom = parentFolderResolvingResult.ResolvedNode;

            filesFromSameFolder = this.GetAllFilesFrom(folderToRemoveFileFrom);

            var fileNode = filesFromSameFolder.FirstOrDefault(file => _namesComparer.Equals(file.Name, fileName));

            if (fileNode == null)
            {
                throw new FileNotFoundException("Не получилось {0} файл (\"{1}\"): файл не найден".FormatWith(verbForPuttingIntoExceptionMessageTemplate, filePath));
            }

            return(fileNode);
        }
        /// <summary>
        /// Возвращает сведения о всех подпапках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>).
        /// </summary>
        /// <param name="folderToGetSubfoldersOf">Папка, поддиректории которой надо вернуть.</param>
        /// <returns>Сведения о всех папках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>)</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        public ReadOnlyCollection <FolderInfo> GetAllFoldersFrom(string folderToGetSubfoldersOf)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderToGetSubfoldersOf, "folderToGetSubfoldersOf");

            try
            {
                NodeWithSurroundingsResolvingResult <FolderNode> nodeResolvingResult = this.ResolveFolderNodeByPath(folderToGetSubfoldersOf);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                return(this.GetAllFoldersFrom(parentFolder)
                       .Select(folderNode => new FolderInfo(folderNode, _pathBuilder.CombinePaths(folderToGetSubfoldersOf, folderNode.Name)))
                       .ToList()
                       .AsReadOnly());
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderToGetSubfoldersOf));
            }
        }
        /// <summary>
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        public NodeWithSurroundingsResolvingResult <FolderNode> ResolveFolderNodeByPath(string path)
        {
            _pathValidator.Validate(path);

            if (_rootFolderPath.Equals(path, StringComparison.Ordinal))
            {
                var rootNode = this.GetRoot();

                return(new NodeWithSurroundingsResolvingResult <FolderNode>(new List <FolderNode> {
                    rootNode
                }, rootNode, null));
            }

            try
            {
                string lastName;

                var nodeResolvingResult = this.ResolveParentFolderNodeByPath(path, out lastName);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                // Note: достаточно выбрать один - все не нужны (но оптимизацию я не делаю).
                ReadOnlyCollection <FolderNode> allFilesUnderFolder = this.GetAllFoldersFrom(parentFolder);

                FolderNode theFolder = allFilesUnderFolder.FirstOrDefault(folder => _namesComparer.Equals(lastName, folder.Name));

                if (theFolder == null)
                {
                    throw new FolderNotFoundException("Папка (\"{0}\") не найдена".FormatWith(path));
                }

                return(new NodeWithSurroundingsResolvingResult <FolderNode>(nodeResolvingResult.FoldersPassedWhileResolving, theFolder, parentFolder));
            }
            catch (CannotResolvePathException)
            {
                throw new FolderNotFoundException("Папка (\"{0}\") не найдена".FormatWith(path));
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="lastName"></param>
        /// <returns></returns>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="CannotResolvePathException"></exception>
        internal NodeResolvingResult <FolderNode> ResolveParentFolderNodeByPath(string path, out string lastName)
        {
            _pathValidator.Validate(path);

            if (_namesComparer.Equals(path, _rootFolderPath))
            {
                throw new InvalidPathException("Нет такой папки, в которой содержится корневая");
            }

            var nodesPassed = new List <FolderNode>();

            string[]   pathParts        = path.Split(new char[] { _directorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
            FolderNode lastNodeResolved = this.GetRoot();

            nodesPassed.Add(lastNodeResolved);

            for (int i = 0; i < pathParts.Length - 1; i++)
            {
                string folderNameToResolve = pathParts[i];

                ReadOnlyCollection <FolderNode> subFolders = this.GetAllFoldersFrom(lastNodeResolved);

                lastNodeResolved =
                    subFolders.FirstOrDefault(subFolder => _namesComparer.Equals(folderNameToResolve, subFolder.Name));

                if (lastNodeResolved == null)
                {
                    throw new CannotResolvePathException("Не удалось найти папку, на которую бы указывал путь \"{0}\"".FormatWith(path));
                }

                nodesPassed.Add(lastNodeResolved);
            }

            lastName = pathParts[pathParts.Length - 1];

            return(new NodeResolvingResult <FolderNode>(nodesPassed, lastNodeResolved));
        }
        public ReadOnlyCollection <FolderNode> GetAllFoldersFrom(FolderNode folderToGetContentsOf)
        {
            if (folderToGetContentsOf == null)
            {
                throw new ArgumentNullException("folderToGetContentsOf");
            }

            if (folderToGetContentsOf.FolderReferencesStreamDefinition.StreamLengthInBytes == 0)
            {
                return(new List <FolderNode>().AsReadOnly());
            }

            var blocksContainingFileNodes = this.ReadAllBlockReferences(folderToGetContentsOf.FolderReferencesStreamDefinition,
                                                                        folderToGetContentsOf);

            var folderNodes = new List <FolderNode>();

            foreach (int fileNodeIndex in blocksContainingFileNodes)
            {
                folderNodes.Add(_fileSystemNodeStorage.ReadFolderNode(fileNodeIndex));
            }

            return(folderNodes.AsReadOnly());
        }
 public NodeWithSurroundingsResolvingResult(IEnumerable <FolderNode> nodesPassedWhileResolvingFromRoot, TNode resolvedNode, FolderNode immediateParent) : base(nodesPassedWhileResolvingFromRoot, resolvedNode)
 {
     ImmediateParent = immediateParent;
 }