2024-04-19 14:34:07 +02:00
package eu.eudat.service.filetransformer ;
2024-03-11 14:01:56 +01:00
import eu.eudat.authorization.AuthorizationFlags ;
import eu.eudat.authorization.Permission ;
import eu.eudat.commonmodels.models.FileEnvelopeModel ;
import eu.eudat.commonmodels.models.description.DescriptionModel ;
import eu.eudat.commonmodels.models.dmp.DmpModel ;
import eu.eudat.commons.enums.StorageType ;
2024-04-19 14:34:07 +02:00
import eu.eudat.commons.types.filetransformer.FileTransformerSourceEntity ;
2024-03-11 14:01:56 +01:00
import eu.eudat.file.transformer.interfaces.FileTransformerConfiguration ;
import eu.eudat.model.Description ;
import eu.eudat.model.Dmp ;
import eu.eudat.model.builder.commonmodels.description.DescriptionCommonModelBuilder ;
import eu.eudat.model.builder.commonmodels.dmp.DmpCommonModelBuilder ;
2024-03-22 12:49:26 +01:00
import eu.eudat.model.file.RepositoryFileFormat ;
2024-03-11 14:01:56 +01:00
import eu.eudat.model.file.TransformerCacheModel ;
import eu.eudat.query.DescriptionQuery ;
import eu.eudat.query.DmpQuery ;
import eu.eudat.service.storage.StorageFileService ;
import gr.cite.commons.web.authz.service.AuthorizationService ;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeCacheService ;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeFilterFunction ;
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeModel ;
import gr.cite.tools.data.builder.BuilderFactory ;
import gr.cite.tools.data.query.QueryFactory ;
import gr.cite.tools.exception.MyNotFoundException ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.context.MessageSource ;
import org.springframework.context.i18n.LocaleContextHolder ;
import org.springframework.stereotype.Service ;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction ;
import org.springframework.web.reactive.function.client.WebClient ;
import reactor.core.publisher.Mono ;
import java.net.URI ;
import java.util.* ;
@Service
public class FileTransformerServiceImpl implements FileTransformerService {
private static final Logger logger = LoggerFactory . getLogger ( FileTransformerServiceImpl . class ) ;
2024-04-01 10:16:19 +02:00
private final FileTransformerProperties fileTransformerProperties ;
2024-04-03 12:22:22 +02:00
private final Map < String , FileTransformerRepository > clients ;
2024-03-11 14:01:56 +01:00
private final TokenExchangeCacheService tokenExchangeCacheService ;
private final FileTransformerConfigurationCache fileTransformerConfigurationCache ;
private final AuthorizationService authorizationService ;
private final QueryFactory queryFactory ;
private final BuilderFactory builderFactory ;
private final StorageFileService storageFileService ;
private final MessageSource messageSource ;
@Autowired
2024-04-01 10:16:19 +02:00
public FileTransformerServiceImpl ( FileTransformerProperties fileTransformerProperties , TokenExchangeCacheService tokenExchangeCacheService , FileTransformerConfigurationCache fileTransformerConfigurationCache , AuthorizationService authorizationService ,
QueryFactory queryFactory , BuilderFactory builderFactory , StorageFileService storageFileService , MessageSource messageSource ) {
this . fileTransformerProperties = fileTransformerProperties ;
2024-03-11 14:01:56 +01:00
this . tokenExchangeCacheService = tokenExchangeCacheService ;
this . fileTransformerConfigurationCache = fileTransformerConfigurationCache ;
this . authorizationService = authorizationService ;
this . queryFactory = queryFactory ;
this . builderFactory = builderFactory ;
this . storageFileService = storageFileService ;
this . messageSource = messageSource ;
this . clients = new HashMap < > ( ) ;
}
2024-04-03 12:22:22 +02:00
private FileTransformerRepository getRepository ( String repoId ) {
2024-03-11 14:01:56 +01:00
if ( this . clients . containsKey ( repoId ) ) return this . clients . get ( repoId ) ;
//GK: It's register time
2024-04-19 14:34:07 +02:00
FileTransformerSourceEntity source = fileTransformerProperties . getSources ( ) . stream ( ) . filter ( depositSource - > depositSource . getTransformerId ( ) . equals ( repoId ) ) . findFirst ( ) . orElse ( null ) ;
2024-03-11 14:01:56 +01:00
if ( source ! = null ) {
String host = URI . create ( source . getUrl ( ) ) . getHost ( ) ;
TokenExchangeModel tokenExchangeModel = new TokenExchangeModel ( host + " _ " + source . getClientId ( ) , source . getIssuerUrl ( ) , source . getClientId ( ) , source . getClientSecret ( ) , source . getScope ( ) ) ;
TokenExchangeFilterFunction tokenExchangeFilterFunction = new TokenExchangeFilterFunction ( this . tokenExchangeCacheService , tokenExchangeModel ) ;
2024-03-22 12:49:26 +01:00
2024-04-03 12:22:22 +02:00
FileTransformerRepository repository = new FileTransformerRepository ( WebClient . builder ( ) . baseUrl ( source . getUrl ( ) + " /api/file-transformer " ) . filters ( exchangeFilterFunctions - > {
2024-03-11 14:01:56 +01:00
exchangeFilterFunctions . add ( tokenExchangeFilterFunction ) ;
exchangeFilterFunctions . add ( logRequest ( ) ) ;
} ) . build ( ) ) ;
2024-03-22 12:49:26 +01:00
this . clients . put ( source . getTransformerId ( ) , repository ) ;
2024-03-11 14:01:56 +01:00
return repository ;
}
return null ;
}
@Override
2024-03-22 12:49:26 +01:00
public List < RepositoryFileFormat > getAvailableExportFileFormats ( ) {
List < RepositoryFileFormat > formats = new ArrayList < > ( ) ;
2024-03-11 14:01:56 +01:00
List < FileTransformerConfiguration > configurations = this . getAvailableConfigurations ( ) ;
if ( configurations ! = null ) {
for ( FileTransformerConfiguration configuration : configurations ) {
2024-04-18 09:08:46 +02:00
if ( configuration ! = null & & configuration . getExportVariants ( ) ! = null ) formats . addAll ( configuration . getExportVariants ( ) . stream ( ) . map ( x - > new RepositoryFileFormat ( configuration . getFileTransformerId ( ) , x , configuration . getExportEntityTypes ( ) ) ) . toList ( ) ) ;
2024-03-11 14:01:56 +01:00
}
}
return formats ;
}
private List < FileTransformerConfiguration > getAvailableConfigurations ( ) {
TransformerCacheModel configs = fileTransformerConfigurationCache . lookup ( " base " ) ;
if ( configs = = null ) {
List < FileTransformerConfiguration > configurations = new ArrayList < > ( ) ;
//GK: So much for lazy loading
2024-04-03 12:22:22 +02:00
List < FileTransformerRepository > repositories = fileTransformerProperties . getSources ( ) . stream ( ) . map ( depositSource - > getRepository ( depositSource . getTransformerId ( ) ) ) . toList ( ) ;
2024-03-11 14:01:56 +01:00
repositories = new ArrayList < > ( repositories ) ;
repositories . forEach ( ( client ) - > {
try {
FileTransformerConfiguration repositoryConfig = client . getConfiguration ( ) ;
if ( repositoryConfig ! = null ) {
configurations . add ( repositoryConfig ) ;
}
} catch ( Exception e ) {
logger . warn ( e . getLocalizedMessage ( ) , e ) ;
}
} ) ;
configs = new TransformerCacheModel ( configurations ) ;
this . fileTransformerConfigurationCache . put ( " base " , configs ) ;
}
return configs . getConfigurations ( ) ;
}
@Override
public eu . eudat . model . file . FileEnvelope exportDmp ( UUID dmpId , String repositoryId , String format ) {
this . authorizationService . authorize ( Permission . EditDmp ) ;
//GK: First get the right client
2024-04-03 12:22:22 +02:00
FileTransformerRepository repository = getRepository ( repositoryId ) ;
if ( repository = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { format , FileTransformerRepository . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
2024-03-11 14:01:56 +01:00
//GK: Second get the Target Data Management Plan
2024-03-12 17:27:16 +01:00
DmpQuery query = this . queryFactory . query ( DmpQuery . class ) . authorize ( AuthorizationFlags . OwnerOrDmpAssociatedOrPermission ) . ids ( dmpId ) ;
2024-03-22 12:49:26 +01:00
DmpModel dmpFileTransformerModel = this . builderFactory . builder ( DmpCommonModelBuilder . class ) . useSharedStorage ( repository . getConfiguration ( ) . isUseSharedStorage ( ) ) . setRepositoryId ( repository . getConfiguration ( ) . getFileTransformerId ( ) ) . authorize ( AuthorizationFlags . OwnerOrDmpAssociatedOrPermission ) . build ( query . first ( ) ) ;
2024-03-11 14:01:56 +01:00
if ( dmpFileTransformerModel = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { dmpId , Dmp . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
FileEnvelopeModel fileEnvelope = repository . exportDmp ( dmpFileTransformerModel , format ) ;
eu . eudat . model . file . FileEnvelope result = new eu . eudat . model . file . FileEnvelope ( ) ;
byte [ ] data = repository . getConfiguration ( ) . isUseSharedStorage ( ) ? storageFileService . readByFileRefAsBytesSafe ( fileEnvelope . getFileRef ( ) , StorageType . Transformer ) : fileEnvelope . getFile ( ) ;
result . setFile ( data ) ;
result . setFilename ( fileEnvelope . getFilename ( ) ) ;
return result ;
}
@Override
2024-03-22 12:49:26 +01:00
public eu . eudat . model . file . FileEnvelope exportDescription ( UUID descriptionId , String repositoryId , String format ) {
2024-03-11 14:01:56 +01:00
this . authorizationService . authorize ( Permission . EditDmp ) ;
//GK: First get the right client
2024-04-03 12:22:22 +02:00
FileTransformerRepository repository = getRepository ( repositoryId ) ;
if ( repository = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { format , FileTransformerRepository . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
2024-03-11 14:01:56 +01:00
//GK: Second get the Target Data Management Plan
2024-03-12 17:27:16 +01:00
DescriptionQuery query = this . queryFactory . query ( DescriptionQuery . class ) . authorize ( AuthorizationFlags . OwnerOrDmpAssociatedOrPermission ) . ids ( descriptionId ) ;
2024-03-22 12:49:26 +01:00
DescriptionModel descriptionFileTransformerModel = this . builderFactory . builder ( DescriptionCommonModelBuilder . class ) . setRepositoryId ( repository . getConfiguration ( ) . getFileTransformerId ( ) ) . useSharedStorage ( repository . getConfiguration ( ) . isUseSharedStorage ( ) ) . authorize ( AuthorizationFlags . OwnerOrDmpAssociatedOrPermission ) . build ( query . first ( ) ) ;
2024-03-11 14:01:56 +01:00
if ( descriptionFileTransformerModel = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { descriptionId , Description . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
FileEnvelopeModel fileEnvelope = repository . exportDescription ( descriptionFileTransformerModel , format ) ;
eu . eudat . model . file . FileEnvelope result = new eu . eudat . model . file . FileEnvelope ( ) ;
byte [ ] data = repository . getConfiguration ( ) . isUseSharedStorage ( ) ? storageFileService . readByFileRefAsBytesSafe ( fileEnvelope . getFileRef ( ) , StorageType . Transformer ) : fileEnvelope . getFile ( ) ; //TODO: shared storage should be per repository
result . setFile ( data ) ;
result . setFilename ( fileEnvelope . getFilename ( ) ) ;
return result ;
}
// This method returns filter function which will log request data
private static ExchangeFilterFunction logRequest ( ) {
return ExchangeFilterFunction . ofRequestProcessor ( clientRequest - > {
logger . info ( " Request: {} {} " , clientRequest . method ( ) , clientRequest . url ( ) ) ;
clientRequest . headers ( ) . forEach ( ( name , values ) - > values . forEach ( value - > logger . info ( " {}={} " , name , value ) ) ) ;
return Mono . just ( clientRequest ) ;
} ) ;
}
}