2023-12-13 10:42:59 +01:00
package eu.eudat.service.deposit ;
import eu.eudat.authorization.AuthorizationFlags ;
import eu.eudat.authorization.Permission ;
2024-03-04 15:36:15 +01:00
import eu.eudat.commonmodels.models.FileEnvelopeModel ;
2024-03-11 14:01:56 +01:00
import eu.eudat.commonmodels.models.description.DescriptionModel ;
import eu.eudat.commonmodels.models.description.FieldModel ;
import eu.eudat.commonmodels.models.description.PropertyDefinitionFieldSetItemModel ;
import eu.eudat.commonmodels.models.description.PropertyDefinitionFieldSetModel ;
2024-03-06 17:18:10 +01:00
import eu.eudat.commonmodels.models.dmp.DmpModel ;
2024-03-11 14:01:56 +01:00
import eu.eudat.commons.enums.StorageType ;
import eu.eudat.commons.scope.user.UserScope ;
2023-12-13 10:42:59 +01:00
import eu.eudat.configurations.deposit.DepositProperties ;
2024-03-11 14:01:56 +01:00
import eu.eudat.convention.ConventionService ;
import eu.eudat.data.DescriptionTemplateEntity ;
2023-12-13 10:42:59 +01:00
import eu.eudat.data.DmpEntity ;
import eu.eudat.depositinterface.repository.DepositClient ;
import eu.eudat.depositinterface.repository.DepositConfiguration ;
2024-03-11 14:01:56 +01:00
import eu.eudat.model.DescriptionTemplate ;
2023-12-13 10:42:59 +01:00
import eu.eudat.model.EntityDoi ;
2024-03-11 14:01:56 +01:00
import eu.eudat.model.StorageFile ;
2024-03-04 15:36:15 +01:00
import eu.eudat.model.builder.commonmodels.DepositConfigurationBuilder ;
2024-03-06 17:18:10 +01:00
import eu.eudat.model.builder.commonmodels.dmp.DmpCommonModelBuilder ;
2024-03-11 14:01:56 +01:00
import eu.eudat.model.persist.StorageFilePersist ;
2023-12-13 10:42:59 +01:00
import eu.eudat.model.persist.deposit.DepositAuthenticateRequest ;
import eu.eudat.model.persist.deposit.DepositRequest ;
import eu.eudat.model.persist.EntityDoiPersist ;
2024-03-11 14:01:56 +01:00
import eu.eudat.query.DescriptionTemplateQuery ;
2023-12-13 10:42:59 +01:00
import eu.eudat.query.DmpQuery ;
import eu.eudat.service.entitydoi.EntityDoiService ;
2024-03-11 14:01:56 +01:00
import eu.eudat.service.storage.StorageFileProperties ;
import eu.eudat.service.storage.StorageFileService ;
import eu.eudat.service.transformer.FileTransformerService ;
2023-12-13 10:42:59 +01:00
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeCacheService ;
2024-03-04 15:36:15 +01:00
import gr.cite.commons.web.authz.service.AuthorizationService ;
2023-12-13 10:42:59 +01:00
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 ;
2024-03-11 14:01:56 +01:00
import gr.cite.tools.fieldset.BaseFieldSet ;
2023-12-13 10:42:59 +01:00
import gr.cite.tools.fieldset.FieldSet ;
2024-03-11 14:01:56 +01:00
import gr.cite.tools.validation.ValidatorFactory ;
import org.apache.commons.io.FilenameUtils ;
2023-12-13 10:42:59 +01:00
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.WebClient ;
2024-03-11 14:01:56 +01:00
import java.io.IOException ;
2023-12-13 10:42:59 +01:00
import java.net.URI ;
2024-03-11 14:01:56 +01:00
import java.net.URLConnection ;
import java.time.Duration ;
import java.util.* ;
import java.util.stream.Collectors ;
2023-12-13 10:42:59 +01:00
@Service
public class DepositServiceImpl implements DepositService {
private static final Logger logger = LoggerFactory . getLogger ( DepositServiceImpl . class ) ;
private final DepositProperties depositProperties ;
private final Map < String , DepositClient > clients ;
private final TokenExchangeCacheService tokenExchangeCacheService ;
private final AuthorizationService authorizationService ;
private final WebClient . Builder webClientBuilder ;
private final EntityDoiService doiService ;
private final QueryFactory queryFactory ;
private final MessageSource messageSource ;
private final BuilderFactory builderFactory ;
private final DepositConfigurationCacheService depositConfigurationCacheService ;
2024-03-11 14:01:56 +01:00
private final FileTransformerService fileTransformerService ;
private final StorageFileService storageFileService ;
private final UserScope userScope ;
private final ValidatorFactory validatorFactory ;
private final StorageFileProperties storageFileProperties ;
private final ConventionService conventionService ;
2023-12-13 10:42:59 +01:00
@Autowired
public DepositServiceImpl ( DepositProperties depositProperties ,
TokenExchangeCacheService tokenExchangeCacheService ,
WebClient . Builder builder ,
AuthorizationService authorizationService ,
EntityDoiService doiService ,
QueryFactory queryFactory ,
MessageSource messageSource ,
2024-03-11 14:01:56 +01:00
BuilderFactory builderFactory , DepositConfigurationCacheService depositConfigurationCacheService , FileTransformerService fileTransformerService , StorageFileService storageFileService , UserScope userScope , ValidatorFactory validatorFactory , StorageFileProperties storageFileProperties , ConventionService conventionService ) {
2023-12-13 10:42:59 +01:00
this . depositProperties = depositProperties ;
this . tokenExchangeCacheService = tokenExchangeCacheService ;
this . authorizationService = authorizationService ;
this . webClientBuilder = builder ;
this . doiService = doiService ;
this . queryFactory = queryFactory ;
this . messageSource = messageSource ;
this . builderFactory = builderFactory ;
this . depositConfigurationCacheService = depositConfigurationCacheService ;
2024-03-11 14:01:56 +01:00
this . fileTransformerService = fileTransformerService ;
this . storageFileService = storageFileService ;
this . userScope = userScope ;
this . validatorFactory = validatorFactory ;
this . storageFileProperties = storageFileProperties ;
this . conventionService = conventionService ;
2023-12-13 10:42:59 +01:00
this . clients = new HashMap < > ( ) ;
}
private DepositClient getDepositClient ( String repositoryId ) {
if ( this . clients . containsKey ( repositoryId ) ) return this . clients . get ( repositoryId ) ;
//GK: It's register time
DepositProperties . DepositSource source = depositProperties . getSources ( ) . stream ( ) . filter ( depositSource - > depositSource . getRepositoryId ( ) . equals ( repositoryId ) ) . findFirst ( ) . orElse ( null ) ;
if ( source ! = null ) {
String host = URI . create ( source . getUrl ( ) ) . getHost ( ) ;
TokenExchangeModel tokenExchangeModel = new TokenExchangeModel ( " deposit: " + source . getRepositoryId ( ) , source . getIssuerUrl ( ) , source . getClientId ( ) , source . getClientSecret ( ) , source . getScope ( ) ) ;
TokenExchangeFilterFunction apiKeyExchangeFilterFunction = new TokenExchangeFilterFunction ( this . tokenExchangeCacheService , tokenExchangeModel ) ;
WebClient webClient = webClientBuilder . baseUrl ( source . getUrl ( ) + " /api/deposit " ) . filters ( exchangeFilterFunctions - > exchangeFilterFunctions . add ( apiKeyExchangeFilterFunction ) ) . build ( ) ;
DepositClientImpl repository = new DepositClientImpl ( webClient ) ;
this . clients . put ( source . getRepositoryId ( ) , repository ) ;
return repository ;
}
return null ;
}
@Override
public List < eu . eudat . model . deposit . DepositConfiguration > getAvailableConfigurations ( FieldSet fieldSet ) {
this . authorizationService . authorizeForce ( Permission . BrowseDeposit ) ;
List < eu . eudat . model . deposit . DepositConfiguration > configurations = new ArrayList < > ( ) ;
for ( DepositProperties . DepositSource depositSource : depositProperties . getSources ( ) ) {
DepositConfigurationCacheService . DepositConfigurationCacheValue cacheValue = this . depositConfigurationCacheService . lookup ( this . depositConfigurationCacheService . buildKey ( depositSource . getRepositoryId ( ) ) ) ;
if ( cacheValue = = null ) {
DepositClient depositClient = getDepositClient ( depositSource . getRepositoryId ( ) ) ;
if ( depositClient = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { depositSource . getRepositoryId ( ) , DepositClient . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
DepositConfiguration configuration = depositClient . getConfiguration ( ) ;
cacheValue = new DepositConfigurationCacheService . DepositConfigurationCacheValue ( depositSource . getRepositoryId ( ) , configuration ) ;
this . depositConfigurationCacheService . put ( cacheValue ) ;
}
eu . eudat . model . deposit . DepositConfiguration depositConfiguration = this . builderFactory . builder ( DepositConfigurationBuilder . class ) . build ( fieldSet , cacheValue . getConfiguration ( ) ) ;
configurations . add ( depositConfiguration ) ;
}
return configurations ;
}
@Override
public EntityDoi deposit ( DepositRequest dmpDepositModel ) throws Exception {
this . authorizationService . authorizeForce ( Permission . EditDeposit ) ;
this . authorizationService . authorize ( Permission . EditDmp ) ;
//GK: First get the right client
DepositClient depositClient = getDepositClient ( dmpDepositModel . getRepositoryId ( ) ) ;
if ( depositClient = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { dmpDepositModel . getRepositoryId ( ) , DepositClient . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
//GK: Second get the Target Data Management Plan
DmpEntity dmpEntity = this . queryFactory . query ( DmpQuery . class ) . ids ( dmpDepositModel . getDmpId ( ) ) . first ( ) ;
if ( dmpEntity = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { dmpDepositModel . getDmpId ( ) , DmpEntity . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
//GK: Forth make the required files to be uploaded with the deposit
//TODO: Properly create required files
2024-03-11 14:01:56 +01:00
DepositProperties . DepositSource source = depositProperties . getSources ( ) . stream ( ) . filter ( depositSource - > depositSource . getRepositoryId ( ) . equals ( dmpDepositModel . getRepositoryId ( ) ) ) . findFirst ( ) . orElse ( null ) ;
if ( source = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { dmpDepositModel . getRepositoryId ( ) , DepositProperties . DepositSource . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
eu . eudat . model . file . FileEnvelope pdfFile = this . fileTransformerService . exportDmp ( dmpEntity . getId ( ) , source . getPdfTransformerId ( ) , " pdf " ) ;
eu . eudat . model . file . FileEnvelope rda = this . fileTransformerService . exportDmp ( dmpEntity . getId ( ) , source . getRdaTransformerId ( ) , " json " ) ;
2024-03-04 15:36:15 +01:00
FileEnvelopeModel pdfEnvelope = new FileEnvelopeModel ( ) ;
FileEnvelopeModel jsonEnvelope = new FileEnvelopeModel ( ) ;
2024-03-11 14:01:56 +01:00
pdfEnvelope . setFilename ( pdfFile . getFilename ( ) ) ;
jsonEnvelope . setFilename ( rda . getFilename ( ) ) ;
if ( ! depositClient . getConfiguration ( ) . isUseSharedStorage ( ) ) {
pdfEnvelope . setFile ( pdfFile . getFile ( ) ) ;
jsonEnvelope . setFile ( rda . getFile ( ) ) ;
} else {
pdfEnvelope . setFileRef ( this . addFileToSharedStorage ( pdfFile ) ) ;
jsonEnvelope . setFileRef ( this . addFileToSharedStorage ( rda ) ) ;
}
2023-12-13 10:42:59 +01:00
//GK: Fifth Transform them to the DepositModel
2024-03-04 15:36:15 +01:00
DmpModel depositModel = this . builderFactory . builder ( DmpCommonModelBuilder . class ) . authorize ( AuthorizationFlags . OwnerOrDmpAssociatedOrPermissionOrPublic )
2024-03-11 14:01:56 +01:00
. setRepositoryId ( dmpDepositModel . getRepositoryId ( ) ) . setPdfFile ( pdfEnvelope ) . setRdaJsonFile ( jsonEnvelope ) . build ( dmpEntity ) ;
//TODO
// if (depositModel != null && !this.conventionService.isListNullOrEmpty(depositModel.getDescriptions())){
// for (DescriptionModel descriptionModel :depositModel.getDescriptions()){
// DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).ids(descriptionModel.getDescriptionTemplate().getId()).firstAs(new BaseFieldSet().ensure(DescriptionTemplate._definition));
// if (descriptionTemplate == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionModel.getDescriptionTemplate().getId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
//
// if (descriptionModel.getProperties() != null && descriptionModel.getProperties().getFieldSets() != null){
// for(PropertyDefinitionFieldSetItemModel propertyDefinitionFieldSetItemModel : descriptionModel.getProperties().getFieldSets().values().stream().filter(x-> x.getItems() != null).map(PropertyDefinitionFieldSetModel::getItems).flatMap(Collection::stream).toList()){
// if (propertyDefinitionFieldSetItemModel.getFields() != null){
// for(Map.Entry<String, FieldModel> entrySet : propertyDefinitionFieldSetItemModel.getFields().entrySet()){
//
// }
// }
// }
// }
//
// }
//
// }
2023-12-13 10:42:59 +01:00
//GK: Sixth Perform the deposit
String doi = depositClient . deposit ( depositModel , dmpDepositModel . getAccessToken ( ) ) ;
//GK: Something has gone wrong return null
if ( doi . isEmpty ( ) ) return null ;
//GK: doi is fine store it in database
EntityDoiPersist doiPersist = new EntityDoiPersist ( ) ;
doiPersist . setRepositoryId ( dmpDepositModel . getRepositoryId ( ) ) ;
doiPersist . setDoi ( doi ) ;
doiPersist . setEntityId ( dmpEntity . getId ( ) ) ;
return doiService . persist ( doiPersist , dmpDepositModel . getProject ( ) ) ;
}
2024-03-11 14:01:56 +01:00
private String addFileToSharedStorage ( eu . eudat . model . file . FileEnvelope file ) throws IOException {
StorageFilePersist storageFilePersist = new StorageFilePersist ( ) ;
storageFilePersist . setName ( FilenameUtils . removeExtension ( file . getFilename ( ) ) ) ;
storageFilePersist . setExtension ( FilenameUtils . getExtension ( file . getFilename ( ) ) ) ;
storageFilePersist . setMimeType ( URLConnection . guessContentTypeFromName ( file . getFilename ( ) ) ) ;
storageFilePersist . setOwnerId ( this . userScope . getUserIdSafe ( ) ) ;
storageFilePersist . setStorageType ( StorageType . Temp ) ;
storageFilePersist . setLifetime ( Duration . ofSeconds ( this . storageFileProperties . getTempStoreLifetimeSeconds ( ) ) ) ; //TODO
this . validatorFactory . validator ( StorageFilePersist . StorageFilePersistValidator . class ) . validateForce ( storageFilePersist ) ;
StorageFile persisted = this . storageFileService . persistBytes ( storageFilePersist , file . getFile ( ) , new BaseFieldSet ( StorageFile . _id , StorageFile . _fileRef ) ) ;
return persisted . getFileRef ( ) ;
}
2023-12-13 10:42:59 +01:00
@Override
public String getLogo ( String repositoryId ) {
this . authorizationService . authorizeForce ( Permission . BrowseDeposit ) ;
DepositClient depositClient = getDepositClient ( repositoryId ) ;
if ( depositClient = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { repositoryId , DepositClient . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
return depositClient . getLogo ( ) ;
}
@Override
public String authenticate ( DepositAuthenticateRequest model ) {
this . authorizationService . authorizeForce ( Permission . BrowseDeposit ) ;
DepositClient depositClient = getDepositClient ( model . getRepositoryId ( ) ) ;
if ( depositClient = = null ) throw new MyNotFoundException ( messageSource . getMessage ( " General_ItemNotFound " , new Object [ ] { model . getRepositoryId ( ) , DepositClient . class . getSimpleName ( ) } , LocaleContextHolder . getLocale ( ) ) ) ;
return depositClient . authenticate ( model . getCode ( ) ) ;
}
}