Ejemplo n.º 1
0
        /// <summary>
        /// Перемещает файл в указанную папку.
        /// </summary>
        /// <param name="currentPathForFile">Полный путь (от корня) к файлу, который следует переместить.</param>
        /// <param name="pathToFolderThatMustContainTheFile">Полный путь к папке, в которую нужно переместить указанный файл (<paramref name="currentPathForFile"/>).</param>
        /// <returns>Описание перемещенного файла, взятое с учетом его нового местоположения.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="MaximumFileCountReachedException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        public FileInfo MoveFile(string currentPathForFile, string pathToFolderThatMustContainTheFile)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(currentPathForFile, "currentPathForFile");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(pathToFolderThatMustContainTheFile, "pathToFolderThatMustContainTheFile");

            try
            {
                var newParentNodeResolvingResult = _nodeResolver.ResolveFolderNodeByPath(pathToFolderThatMustContainTheFile);

                FolderNode filesNewHome = newParentNodeResolvingResult.ResolvedNode;

                string fileName;

                var currentParentFolder = _nodeResolver.ResolveParentFolderNodeByPath(currentPathForFile, out fileName);

                ReadOnlyCollection <FileNode> allFilesInTheFolder;
                FolderNode folderToRemoveFileFrom = currentParentFolder.ResolvedNode;
                FileNode   fileToMove             = this.ResolveFileNodeThrowingUserFriendlyErrors(currentPathForFile, currentParentFolder, fileName, "переместить", out allFilesInTheFolder);

                var allFilesInDestinationFolder = _nodeResolver.GetAllFilesFrom(filesNewHome);

                // перемещение в то место, где файл и так уже находится.
                if (newParentNodeResolvingResult.ResolvedNode.Id.Equals(currentParentFolder.ResolvedNode.Id))
                {
                    return(new FileInfo(allFilesInDestinationFolder.First(fileNode => _namesComparer.Equals(fileNode.Name, fileName)), currentPathForFile));
                }

                if (allFilesInDestinationFolder.Any(fileNode => _namesComparer.Equals(fileNode.Name, fileName)))
                {
                    throw new FileAlreadyExistsException("Перемещение файла невозможно: в папке \"{0}\" уже существует файл с именем \"{1}\"".FormatWith(pathToFolderThatMustContainTheFile, fileName));
                }

                // сначала добавляем ссылку в новую папку, потом удаляем ссылку из старой (на добавление может не хватить места, удалить же можно всегда).
                _blockReferenceListsEditor.AddBlockReference(fileToMove.DiskBlockIndex, filesNewHome.FileReferencesStreamDefinition, filesNewHome);
                // TODO: поглядеть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveFileFrom, fileToMove.DiskBlockIndex, folderToRemoveFileFrom.FileReferencesStreamDefinition);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(newParentNodeResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(newParentNodeResolvingResult.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(currentParentFolder.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(currentParentFolder.ResolvedNode.Id);

                allFilesInDestinationFolder = _nodeResolver.GetAllFilesFrom(filesNewHome);

                return(new FileInfo(
                           allFilesInDestinationFolder.Single(fileNode => _namesComparer.Equals(fileNode.Name, fileName)),
                           _pathBuilder.CombinePaths(pathToFolderThatMustContainTheFile, fileName)));
            }
            catch (InsufficientSpaceException)
            {
                throw new InsufficientSpaceException("Не удалось переместить файл из \"{0}\" в \"{1}\" - не хватает места на диске для проведения операции.".FormatWith(currentPathForFile, pathToFolderThatMustContainTheFile));
            }
            catch (MaximumFileSizeReachedException)
            {
                throw new MaximumFileCountReachedException("Не удалось переместить файл \"{0}\". Папка \"{1}\" не может вместить больше файлов, чем уже вмещает".FormatWith(currentPathForFile, pathToFolderThatMustContainTheFile));
            }
            catch (CannotResolvePathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
            catch (InvalidPathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
        }
        /// <summary>
        /// Перемещает папку в указанную директорию.
        /// </summary>
        /// <param name="currentPathForFolder">Полный путь (от корня) к папке, которую следует переместить.</param>
        /// <param name="pathToFolderThatWillContainTheFolderMoved">Полный путь к папке, в которую нужно переместить указанную директорию (<paramref name="currentPathForFolder"/>).</param>
        /// <returns>Описание перемещенной папки, взятое с учетом ее нового местоположения.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderLockedException"></exception>
        /// <exception cref="FolderAlreadyExistsException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="MaximumFolderCountReachedException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="InvalidOperationException">Если пытаетесь переместить папку в одну из ее собственных поддиректорий.</exception>
        public FolderInfo MoveFolder(string currentPathForFolder, string pathToFolderThatWillContainTheFolderMoved)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(currentPathForFolder, "cucurrentPathForFolderrrentPathForFile");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(pathToFolderThatWillContainTheFolderMoved, "pathToFolderThatWillContainTheFolderMoved");

            try
            {
                var newParentNodeResolvingResult =
                    _nodeResolver.ResolveFolderNodeByPath(pathToFolderThatWillContainTheFolderMoved);

                FolderNode foldersNewHome = newParentNodeResolvingResult.ResolvedNode;

                string folderName;

                var currentParentFolder = _nodeResolver.ResolveParentFolderNodeByPath(currentPathForFolder, out folderName);

                FolderNode folderToRemoveDirectoryFrom = currentParentFolder.ResolvedNode;

                var directoriesInFolder = _nodeResolver.GetAllFoldersFrom(folderToRemoveDirectoryFrom);

                FolderNode folderToMove =
                    directoriesInFolder.FirstOrDefault(fileNode => _namesComparer.Equals(fileNode.Name, folderName));

                if (folderToMove == null)
                {
                    throw new FolderNotFoundException("Не найдена папка для перемещения (\"{0}\")".FormatWith(currentPathForFolder));
                }

                if (newParentNodeResolvingResult.FoldersPassedWhileResolving.Any(folderNode => folderNode.Id.Equals(folderToMove.Id)))
                {
                    throw new InvalidOperationException("Операция перемещения папки \"{0}\" в \"{1}\" отменена: невозможно переместить папку в одну из ее же поддиректорий.".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved));
                }

                if (_lockingManager.IsNodeLockedForRenamesAndMoves(folderToMove))
                {
                    throw new FolderLockedException("Не удалось переместить папку (\"{0}\"): она или любая из ее поддиректорий содержит файлы открытые сейчас для чтения или записи.".FormatWith(currentPathForFolder));
                }

                var allSubfoldersOfDestinationFolder = _nodeResolver.GetAllFoldersFrom(foldersNewHome);

                var idsOfAllSubfolders = _nodeResolver.GetIdsOfAllFoldersUnderGivenOne(currentPathForFolder);

                // перемещение в то место, где файл и так уже находится.)
                if (newParentNodeResolvingResult.ResolvedNode.Id.Equals(currentParentFolder.ResolvedNode.Id))
                {
                    return(new FolderInfo(allSubfoldersOfDestinationFolder.First(fileNode => _namesComparer.Equals(fileNode.Name, folderName)), currentPathForFolder));
                }

                if (allSubfoldersOfDestinationFolder.Any(fileNode => _namesComparer.Equals(fileNode.Name, folderName)))
                {
                    throw new FolderAlreadyExistsException("Перемещение папки невозможно: в директории \"{0}\" уже существует папка с именем \"{1}\"".FormatWith(pathToFolderThatWillContainTheFolderMoved, folderName));
                }

                // сначала добавляем ссылку в новую папку, потом удаляем ссылку из старой (на добавление может не хватить места, удалить же можно всегда).
                _blockReferenceListsEditor.AddBlockReference(folderToMove.DiskBlockIndex, foldersNewHome.FolderReferencesStreamDefinition, foldersNewHome);
                // TODO: поглядеть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveDirectoryFrom, folderToMove.DiskBlockIndex, folderToRemoveDirectoryFrom.FolderReferencesStreamDefinition);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(newParentNodeResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(newParentNodeResolvingResult.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(currentParentFolder.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(currentParentFolder.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(idsOfAllSubfolders);

                allSubfoldersOfDestinationFolder = _nodeResolver.GetAllFoldersFrom(foldersNewHome);

                return(new FolderInfo(
                           allSubfoldersOfDestinationFolder.Single(folderNode => _namesComparer.Equals(folderNode.Name, folderName)),
                           _pathBuilder.CombinePaths(pathToFolderThatWillContainTheFolderMoved, folderName)));
            }
            catch (InsufficientSpaceException)
            {
                throw new InsufficientSpaceException("Не удалось переместить папку из \"{0}\" в \"{1}\" - не хватает места на диске для проведения операции.".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved));
            }
            catch (MaximumFileSizeReachedException)
            {
                throw new MaximumFolderCountReachedException("Не удалось переместить папку \"{0}\". Папка \"{1}\" не может вместить больше файлов, чем уже вмещает".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved));
            }
            catch (CannotResolvePathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
            catch (InvalidPathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
        }