adding features
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::application::dtos::file_dto::FileDto;
|
||||
use crate::application::ports::file_ports::FileManagementUseCase;
|
||||
use crate::application::ports::storage_ports::FileWritePort;
|
||||
use crate::common::errors::DomainError;
|
||||
|
||||
/// Servicio para operaciones de gestión de archivos
|
||||
pub struct FileManagementService {
|
||||
file_repository: Arc<dyn FileWritePort>,
|
||||
}
|
||||
|
||||
impl FileManagementService {
|
||||
/// Crea un nuevo servicio de gestión de archivos
|
||||
pub fn new(file_repository: Arc<dyn FileWritePort>) -> Self {
|
||||
Self { file_repository }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl FileManagementUseCase for FileManagementService {
|
||||
async fn move_file(&self, file_id: &str, folder_id: Option<String>) -> Result<FileDto, DomainError> {
|
||||
tracing::info!("Moviendo archivo con ID: {} a carpeta: {:?}", file_id, folder_id);
|
||||
|
||||
let moved_file = self.file_repository.move_file(file_id, folder_id).await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error al mover archivo (ID: {}): {}", file_id, e);
|
||||
e
|
||||
})?;
|
||||
|
||||
tracing::info!("Archivo movido exitosamente: {} (ID: {}) a carpeta: {:?}",
|
||||
moved_file.name(), moved_file.id(), moved_file.folder_id());
|
||||
|
||||
Ok(FileDto::from(moved_file))
|
||||
}
|
||||
|
||||
async fn delete_file(&self, id: &str) -> Result<(), DomainError> {
|
||||
self.file_repository.delete_file(id).await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
|
||||
use crate::application::dtos::file_dto::FileDto;
|
||||
use crate::application::ports::file_ports::FileRetrievalUseCase;
|
||||
use crate::application::ports::storage_ports::FileReadPort;
|
||||
use crate::common::errors::DomainError;
|
||||
|
||||
/// Servicio para operaciones de recuperación de archivos
|
||||
pub struct FileRetrievalService {
|
||||
file_repository: Arc<dyn FileReadPort>,
|
||||
}
|
||||
|
||||
impl FileRetrievalService {
|
||||
/// Crea un nuevo servicio de recuperación de archivos
|
||||
pub fn new(file_repository: Arc<dyn FileReadPort>) -> Self {
|
||||
Self { file_repository }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl FileRetrievalUseCase for FileRetrievalService {
|
||||
async fn get_file(&self, id: &str) -> Result<FileDto, DomainError> {
|
||||
let file = self.file_repository.get_file(id).await?;
|
||||
Ok(FileDto::from(file))
|
||||
}
|
||||
|
||||
async fn list_files(&self, folder_id: Option<&str>) -> Result<Vec<FileDto>, DomainError> {
|
||||
let files = self.file_repository.list_files(folder_id).await?;
|
||||
Ok(files.into_iter().map(FileDto::from).collect())
|
||||
}
|
||||
|
||||
async fn get_file_content(&self, id: &str) -> Result<Vec<u8>, DomainError> {
|
||||
self.file_repository.get_file_content(id).await
|
||||
}
|
||||
|
||||
async fn get_file_stream(&self, id: &str) -> Result<Box<dyn Stream<Item = Result<Bytes, std::io::Error>> + Send>, DomainError> {
|
||||
self.file_repository.get_file_stream(id).await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::application::dtos::file_dto::FileDto;
|
||||
use crate::application::ports::file_ports::FileUploadUseCase;
|
||||
use crate::application::ports::storage_ports::FileWritePort;
|
||||
use crate::common::errors::DomainError;
|
||||
|
||||
/// Servicio para operaciones de subida de archivos
|
||||
pub struct FileUploadService {
|
||||
file_repository: Arc<dyn FileWritePort>,
|
||||
}
|
||||
|
||||
impl FileUploadService {
|
||||
/// Crea un nuevo servicio de subida de archivos
|
||||
pub fn new(file_repository: Arc<dyn FileWritePort>) -> Self {
|
||||
Self { file_repository }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl FileUploadUseCase for FileUploadService {
|
||||
async fn upload_file(
|
||||
&self,
|
||||
name: String,
|
||||
folder_id: Option<String>,
|
||||
content_type: String,
|
||||
content: Vec<u8>,
|
||||
) -> Result<FileDto, DomainError> {
|
||||
let file = self.file_repository.save_file(name, folder_id, content_type, content).await?;
|
||||
Ok(FileDto::from(file))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::application::ports::file_ports::{FileUploadUseCase, FileRetrievalUseCase, FileManagementUseCase, FileUseCaseFactory};
|
||||
use crate::application::services::file_upload_service::FileUploadService;
|
||||
use crate::application::services::file_retrieval_service::FileRetrievalService;
|
||||
use crate::application::services::file_management_service::FileManagementService;
|
||||
use crate::application::ports::storage_ports::{FileReadPort, FileWritePort};
|
||||
|
||||
/// Factory para crear implementaciones de casos de uso de archivos
|
||||
pub struct AppFileUseCaseFactory {
|
||||
file_read_repository: Arc<dyn FileReadPort>,
|
||||
file_write_repository: Arc<dyn FileWritePort>,
|
||||
}
|
||||
|
||||
impl AppFileUseCaseFactory {
|
||||
/// Crea una nueva factory para casos de uso de archivos
|
||||
pub fn new(
|
||||
file_read_repository: Arc<dyn FileReadPort>,
|
||||
file_write_repository: Arc<dyn FileWritePort>
|
||||
) -> Self {
|
||||
Self {
|
||||
file_read_repository,
|
||||
file_write_repository,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileUseCaseFactory for AppFileUseCaseFactory {
|
||||
fn create_file_upload_use_case(&self) -> Arc<dyn FileUploadUseCase> {
|
||||
Arc::new(FileUploadService::new(self.file_write_repository.clone()))
|
||||
}
|
||||
|
||||
fn create_file_retrieval_use_case(&self) -> Arc<dyn FileRetrievalUseCase> {
|
||||
Arc::new(FileRetrievalService::new(self.file_read_repository.clone()))
|
||||
}
|
||||
|
||||
fn create_file_management_use_case(&self) -> Arc<dyn FileManagementUseCase> {
|
||||
Arc::new(FileManagementService::new(self.file_write_repository.clone()))
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,17 @@
|
||||
pub mod batch_operations;
|
||||
pub mod file_service;
|
||||
pub mod folder_service;
|
||||
pub mod i18n_application_service;
|
||||
pub mod storage_mediator;
|
||||
pub mod batch_operations;
|
||||
|
||||
// Nuevos servicios refactorizados
|
||||
pub mod file_upload_service;
|
||||
pub mod file_retrieval_service;
|
||||
pub mod file_management_service;
|
||||
pub mod file_use_case_factory;
|
||||
|
||||
// Re-exportar para facilitar acceso
|
||||
pub use file_upload_service::FileUploadService;
|
||||
pub use file_retrieval_service::FileRetrievalService;
|
||||
pub use file_management_service::FileManagementService;
|
||||
pub use file_use_case_factory::AppFileUseCaseFactory;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use async_trait::async_trait;
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -97,9 +98,9 @@ pub trait StorageMediator: Send + Sync + 'static {
|
||||
|
||||
/// Implementación concreta del mediador de almacenamiento
|
||||
pub struct FileSystemStorageMediator {
|
||||
folder_repository: Arc<dyn FolderRepository>,
|
||||
path_service: Arc<PathService>,
|
||||
id_mapping: Arc<dyn IdMappingPort>,
|
||||
pub folder_repository: Arc<dyn FolderRepository>,
|
||||
pub path_service: Arc<PathService>,
|
||||
pub id_mapping: Arc<dyn IdMappingPort>,
|
||||
}
|
||||
|
||||
impl FileSystemStorageMediator {
|
||||
@@ -111,6 +112,86 @@ impl FileSystemStorageMediator {
|
||||
pub fn new_stub() -> StubStorageMediator {
|
||||
StubStorageMediator::new()
|
||||
}
|
||||
|
||||
/// Overload para implementar inicialización diferida con repository placeholder
|
||||
pub fn new_with_lazy_folder(
|
||||
folder_repository: Arc<RwLock<Option<Arc<dyn FolderRepository>>>>,
|
||||
path_service: Arc<PathService>,
|
||||
id_mapping: Arc<dyn IdMappingPort>
|
||||
) -> Self {
|
||||
// Create temporary stub repository
|
||||
let temp_repo = Arc::new(FolderRepositoryStub {});
|
||||
|
||||
Self {
|
||||
folder_repository: temp_repo,
|
||||
path_service,
|
||||
id_mapping,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Stub repository for initialization
|
||||
#[derive(Debug)]
|
||||
pub struct FolderRepositoryStub {}
|
||||
|
||||
#[async_trait]
|
||||
impl FolderRepository for FolderRepositoryStub {
|
||||
async fn create_folder(&self, _name: String, _parent_id: Option<String>) -> Result<Folder, FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn get_folder_by_id(&self, _id: &str) -> Result<Folder, FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn get_folder_by_storage_path(&self, _storage_path: &StoragePath) -> Result<Folder, FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn list_folders(&self, _parent_id: Option<&str>) -> Result<Vec<Folder>, FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn list_folders_paginated(
|
||||
&self,
|
||||
_parent_id: Option<&str>,
|
||||
_offset: usize,
|
||||
_limit: usize,
|
||||
_include_total: bool
|
||||
) -> Result<(Vec<Folder>, Option<usize>), FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn rename_folder(&self, _id: &str, _new_name: String) -> Result<Folder, FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn move_folder(&self, _id: &str, _new_parent_id: Option<&str>) -> Result<Folder, FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn delete_folder(&self, _id: &str) -> Result<(), FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
|
||||
async fn folder_exists_at_storage_path(&self, _storage_path: &StoragePath) -> Result<bool, FolderRepositoryError> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
async fn get_folder_storage_path(&self, _id: &str) -> Result<StoragePath, FolderRepositoryError> {
|
||||
Ok(StoragePath::root())
|
||||
}
|
||||
|
||||
// Legacy methods
|
||||
#[allow(deprecated)]
|
||||
async fn folder_exists(&self, _path: &std::path::PathBuf) -> Result<bool, FolderRepositoryError> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
async fn get_folder_by_path(&self, _path: &std::path::PathBuf) -> Result<Folder, FolderRepositoryError> {
|
||||
Err(FolderRepositoryError::Other("Stub repository".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Stub implementation for initialization dependency issues
|
||||
|
||||
Reference in New Issue
Block a user